[dmd-concurrency] What is protected by synchronization?
Robert Jacques
sandford at jhu.edu
Sat Jan 30 14:25:15 PST 2010
On Sat, 30 Jan 2010 15:30:04 -0500, Michel Fortin
<michel.fortin at michelf.com> wrote:
> Le 2010-01-30 à 9:57, Michel Fortin a écrit :
>
>> Since we're talking about synchronization again, I think this is a
>> problem that should be addressed.
>
> (Replying to myself)
>
> Robert's comment in the other thread makes me realize I've skipped over
> something important in my previous message: fields inside a synchronized
> object shouldn't 'shared'. Despite being usable from many threads due to
> synchronization, they behave much more like thread-local fields where
> the thread they belong to changes depending on who holds the lock.
I assume this is only for value types and not references.
> So what I'm proposing is that a synchronized object contains non-shared
> fields unless explicitly marked shared. Those fields wouldn't be
> accessible from anywhere except inside a synchronized block. Inside a
> synchronized block they are accessible and treated as thread-local.
Except shared functions can return thread-local objects, which will cause
escapes in the model. And class instance A could give references to class
instance B, resulting in an escape.
> The only thing lacking is a way to avoid them from escaping when passing
> them to functions. If we deem it necessary, we could add a type modifier
> for that (although it probably won't enough by itself).
The type modifier you are looking for is called 'owned'. Bartosz went into
some detail of it on his blog. From a runtime perspective, owned objects
are all protected by a common mutex, and are therefore shared objects.
From a compile time perspective, it provides the ability to optimize away
some recursive locks, etc.
> But as long as the programmer doesn't let those references escape,
> things will run smoothly. I think having fined-grained controls over
> what is protected by the lock and what will use atomic operations is a
> necessity if you want to achieve decent performances.
>
> More examples:
>
> synchronized class SyncObject {
> shared(int)*[] data;
> // only the last part can be shared,
> // the rest is protected by the object's lock.
>
> SyncObject next;
> // the reference is protected by the object's lock,
> // but the object itself can be shared since it is synchronized.
>
> char[] buffer;
> // the whole thing is protected by the object's lock.
>
> SomeStruct s;
> // s.a is protected by the object's lock.
> // s.b is shared as per struct's definition.
> // s.test() is callable under the object's lock.
> }
>
> struct SomeStruct {
> int a;
> shared(int) b;
>
> void test() {
> a += 1;
> b += 1; // this one is always atomic.
> }
> }
>
>
More information about the dmd-concurrency
mailing list