[dmd-concurrency] synchronized, shared, and regular methods inside the same class

Sean Kelly sean at invisibleduck.org
Tue Jan 5 16:58:44 PST 2010


On Jan 4, 2010, at 5:16 PM, Jason House wrote:

> On Jan 4, 2010, at 8:00 PM, Andrei Alexandrescu <andrei at erdani.com> wrote:
>> 
>> Same here. All - please advise.
> 
> I like this style as long as the compiler isn't completely brain dead and incorrectly force sme to put sharedRead and sharedWrite throughout my code base. I actually have a tweaked set of Tango's atomics in my D2 code base. We can't forget CAS and atomic increment/decrement for shared data.

I created the Tango atomics module and would love to roll it into Druntime in some form.  At the very least I agree that we need a CAS operation.

>>> The only catch with the approach above (and you've mentioned this before) is:
>>>   class A {
>>>       void fnA() shared { x = 5; }
>>>       void fnB() synchronized { x = 6; }
>>>       int x;
>>>   }
>>> I had thought that explicitly labeling variables as shared would sidestep this by requiring ops on the vars to always be atomic.  An alternative (as you've said before) would be to not allow shared and synchronized methods to both be used in a class, but it's pretty common that I'll want to do something like this:
>>>   class A {
>>>       void fnA() synchronized { sharedWrite( flag, true ); }
>>>       void fnB() shared { return sharedRead( flag ); }
>>>       shared flag;
>>>   }
>>> Maybe my explicitly declaring flag as shared somehow provides an exemption?  Or did you have another idea for a way around this?
>> 
>> Hmmm... if a field is shared in a non-shared object, it means you're not using object's own lock to control access to that field. (You can e.g. assume that other threads have the address of that field.) So that field, inside a synchronized method, will not benefit of the tail-shared exemption and will be subjected to all limitations specific to e.g. a shared global bool.
> 
> 
> It's worse than that. Notice how in Sean's code that he didn't replace the sharedWrite call with a more conventional assignment. One really wants to keep full protection with (most) lock free variables. This means always using sharedRead and sharedWrite with them. The compiler should facilitate this...

Yeah, if a shared variable is ever accessed outside a synchronized method then all accesses to it must be made atomic.  This is why I'd previously thought that shared fields would be explicitly labeled as such, and the non-labeled fields could only be accessed in a synchronized method.  I'm personally fine with using sharedRead and sharedWrite in this instance because only a handful of variables would ever be labeled as shared.  Things are obviously quite different if the shared attribute of a class instance extends to all of its fields, and the compiler is expected to optimize away what it can though.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/dmd-concurrency/attachments/20100105/673be981/attachment.htm>


More information about the dmd-concurrency mailing list