synchronized (this[.classinfo]) in druntime and phobos

deadalnix deadalnix at gmail.com
Wed May 30 06:40:38 PDT 2012


Le 30/05/2012 14:55, Dmitry Olshansky a écrit :
> On 30.05.2012 16:43, Regan Heath wrote:
>> On Wed, 30 May 2012 00:10:19 +0100, Jonathan M Davis
>> <jmdavisProg at gmx.com> wrote:
>>
>>> On Wednesday, May 30, 2012 01:02:53 Alex Rønne Petersen wrote:
>>>> But mutexes allow proper encapsulation by hiding the mutex resource. As
>>>> I've proven in the very OP of this thread, both druntime and phobos
>>>> suffer from the anti-pattern that is locking on a public resource when
>>>> you shouldn't. The language encourages doing it with this synchronized
>>>> business.
>>>
>>>> From your comments, it sounds to me like the problem is entirely with
>>> synchronized blocks, not sychronized classes. Synchronized classes
>>> don't have
>>> the issue of having externals lock on them without the explicit use of
>>> synchronized blocks. They're the equivalent of locking a mutex in
>>> every public
>>> function and releasing it afterwards. The problem is that that mutex is
>>> effectively public such that when a synchronized block is used on it,
>>> it locks
>>> on the same mutex. If no synchronized blocks are used, as far as I can
>>> tell,
>>> it's a non-issue.
>>>
>>> As such, wouldn't simply making the use of a sychronized block on a
>>> synchronized object illegal fix the problem?
>>
>> Not in all cases. If you have a synchronized class, say a thread-safe
>> container, which has a synchronized lookup and synchronized insert
>> function, code like..
>>
>> if (!o.lookup(...))
>> o.insert(...)
>>
>> obtains and releases the mutex twice each, and in between another thread
>> could call o.insert() and insert the missing object - resulting in 2
>> copies being inserted (or a duplicate insert exception being throw,
>> or...).
>>
>> Now, the above is bad design, but the only other choice is to expose
>> lock() and unlock() methods (or the mutex - back to square 1one) to
>> allow locking around multiple class, but now the caller has to be
>> careful to call unlock in all code paths. scope helps us in D, but this
>> is actually the whole point of synchronized blocks - 1. ensuring the
>> unlock always happens and 2. making the scope of the locking visible in
>> the code.
>>
> synchronized class Container
> {
>
> void applyLocked(scope delegate void(Container _this));
> ...
> }
>
>

I often ends up doing similar stuff when manipulating pair of actions. 
lock/unlock, connect/disconect, begin/commit/rollback, etc . . .


More information about the Digitalmars-d mailing list