www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - basic concurrency

reply Tydr Schnubbis <fake address.dude> writes:
If I have an array and want to synchronize all access to it (only one 
thread using it at a time), what's the best way?  I know how to use 
'synchronized' to make a critical section, but I want to synchronize 
data, not code.
Apr 18 2006
next sibling parent reply Frank Benoit <keinfarbton nospam.xyz> writes:
Tydr Schnubbis schrieb:
 If I have an array and want to synchronize all access to it (only one
 thread using it at a time), what's the best way?  I know how to use
 'synchronized' to make a critical section, but I want to synchronize
 data, not code.

i am not completely sure, but does this make sense? if you want to access the array consitently, you have to synchronize multiple accesses. int[10] a; a[0] = a[0] +1; => how can the data sychronization know that there should be a lock until the write? I would write a class, encapsulating the data and all accesses to them. So you can use the existing thread synchronisation.
Apr 18 2006
parent reply Tydr Schnubbis <fake address.dude> writes:
Frank Benoit wrote:
 Tydr Schnubbis schrieb:
 If I have an array and want to synchronize all access to it (only one
 thread using it at a time), what's the best way?  I know how to use
 'synchronized' to make a critical section, but I want to synchronize
 data, not code.

i am not completely sure, but does this make sense? if you want to access the array consitently, you have to synchronize multiple accesses. int[10] a; a[0] = a[0] +1; => how can the data sychronization know that there should be a lock until the write? I would write a class, encapsulating the data and all accesses to them. So you can use the existing thread synchronisation.

say I have this: class MyArray { private int[] array; int get(size_t i) { return array[i]; } void append(int v) { array ~= v; } } How do I use 'synchronized' to make sure get() and append() can't be called simultaneously by two or more different threads?
Apr 18 2006
parent reply Frank Benoit <keinfarbton nospam.xyz> writes:
 How do I use 'synchronized' to make sure get() and append() can't be
 called simultaneously by two or more different threads?

class MyArray { private int[] array; int get(size_t i){ synchronized(this){ return array[i]; } } void append(int v){ synchronized(this){ array ~= v; } } } the synchronized statement used the object instance reference of MyArray like a binary semaphore. It is guaranteed only one thread at a time and object can pass the barrier. I don't know, perhaps the "(this)" can be omitted.
Apr 18 2006
parent reply kris <foo bar.com> writes:
Frank Benoit wrote:
How do I use 'synchronized' to make sure get() and append() can't be
called simultaneously by two or more different threads?

class MyArray { private int[] array; int get(size_t i){ synchronized(this){ return array[i]; } } void append(int v){ synchronized(this){ array ~= v; } } } the synchronized statement used the object instance reference of MyArray like a binary semaphore. It is guaranteed only one thread at a time and object can pass the barrier. I don't know, perhaps the "(this)" can be omitted.

Like Frank said, you can prohibit simultaneous access by using the "synchronized" keyword (just like Java). His example shows synchronizing on a specific object, although you can also synch on the container: synchronized void get(size_t i) { ... } In this case, the effect is the same in both examples. For situations where high throughput is a concern, you'd likely want to use a lock-free design instead. There's not many of those around since they're tricky to write -- however, as John noted earlier, there's a port of Doug Lea's ConcurrentHashMap available; it gets by with no locks at all, in the general cases. Makes it a really good choice where thread contention is evident.
Apr 18 2006
parent reply Tydr Schnubbis <fake address.dude> writes:
kris wrote:
 Frank Benoit wrote:
How do I use 'synchronized' to make sure get() and append() can't be
called simultaneously by two or more different threads?

class MyArray { private int[] array; int get(size_t i){ synchronized(this){ return array[i]; } } void append(int v){ synchronized(this){ array ~= v; } } } the synchronized statement used the object instance reference of MyArray like a binary semaphore. It is guaranteed only one thread at a time and object can pass the barrier. I don't know, perhaps the "(this)" can be omitted.

Like Frank said, you can prohibit simultaneous access by using the "synchronized" keyword (just like Java). His example shows synchronizing on a specific object, although you can also synch on the container: synchronized void get(size_t i) { ... } In this case, the effect is the same in both examples.

When one thread executes a synchronized, piece of code, can another thread execute another piece of synchronized code? The way I read the D docs, it can. But how can this work if that's true? That only one thread can execute the 'get' method at any given time doesn't help if another thread at the same time can execute another method that modifies the same array. And this syntax: synchronized void get(size_t i) {} Does this allow get to be run only by one thread for all the objects of the class, or one thread per object, like synchronized (this) {} does?
Apr 18 2006
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Tydr Schnubbis wrote:
 
 When one thread executes a synchronized, piece of code, can another 
 thread execute another piece of synchronized code?  The way I read the D 
 docs, it can.  But how can this work if that's true?  That only one 
 thread can execute the 'get' method at any given time doesn't help if 
 another thread at the same time can execute another method that modifies 
 the same array.
 
 And this syntax:
 synchronized void get(size_t i) {}
 
 Does this allow get to be run only by one thread for all the objects of 
 the class, or one thread per object, like synchronized (this) {} does?

I believe 'synchronized' applied to an object method synchronized on that object, while 'synchronized' applied to a static method synchronizes on that type's ClassInfo object. Finally, 'synchronized' in free functions synchronizes on the global monitor. Does that help? Sean
Apr 18 2006
parent Tydr Schnubbis <fake address.dude> writes:
Sean Kelly wrote:
 Tydr Schnubbis wrote:
 
 When one thread executes a synchronized, piece of code, can another 
 thread execute another piece of synchronized code?  The way I read the D 
 docs, it can.  But how can this work if that's true?  That only one 
 thread can execute the 'get' method at any given time doesn't help if 
 another thread at the same time can execute another method that modifies 
 the same array.
 
 And this syntax:
 synchronized void get(size_t i) {}
 
 Does this allow get to be run only by one thread for all the objects of 
 the class, or one thread per object, like synchronized (this) {} does?

I believe 'synchronized' applied to an object method synchronized on that object, while 'synchronized' applied to a static method synchronizes on that type's ClassInfo object. Finally, 'synchronized' in free functions synchronizes on the global monitor. Does that help?

important for me to understand the answer to. But thanks anyway. :)
Apr 18 2006
prev sibling parent kris <foo bar.com> writes:
Tydr Schnubbis wrote:
 kris wrote:
 
 Frank Benoit wrote:

 How do I use 'synchronized' to make sure get() and append() can't be
 called simultaneously by two or more different threads?

class MyArray { private int[] array; int get(size_t i){ synchronized(this){ return array[i]; } } void append(int v){ synchronized(this){ array ~= v; } } } the synchronized statement used the object instance reference of MyArray like a binary semaphore. It is guaranteed only one thread at a time and object can pass the barrier. I don't know, perhaps the "(this)" can be omitted.

Like Frank said, you can prohibit simultaneous access by using the "synchronized" keyword (just like Java). His example shows synchronizing on a specific object, although you can also synch on the container: synchronized void get(size_t i) { ... } In this case, the effect is the same in both examples.

When one thread executes a synchronized, piece of code, can another thread execute another piece of synchronized code? The way I read the D docs, it can. But how can this work if that's true? That only one thread can execute the 'get' method at any given time doesn't help if another thread at the same time can execute another method that modifies the same array.

multiple threads can be executing sections of code at the same time, only if that code is guarded by different and distinct locks (or not guarded at all). The simple case of synch, with D objects, will protect each object instance against multi-thread collisions. Think of it as a per-object mutex.
 
 And this syntax:
 synchronized void get(size_t i) {}
 
 Does this allow get to be run only by one thread for all the objects of 
 the class, or one thread per object, like synchronized (this) {} does?

No -- it's per instance, like synchronized(this). If you want to synch across all class instances, then you could synch on the appropriate classinfo instead of 'this'.
Apr 18 2006
prev sibling parent John Demme <me teqdruid.com> writes:
Tydr Schnubbis wrote:

 If I have an array and want to synchronize all access to it (only one
 thread using it at a time), what's the best way?  I know how to use
 'synchronized' to make a critical section, but I want to synchronize
 data, not code.

In Mango, Doug Lea's Concurrency library has been ported from Java. It's got locks and such. You can create a ReadWriteLock to go along with that data object and everything that wants to use the object can get a lock before it does so. Alternatively, I already have a ThreadSafeList wrapper class (which uses a ReentrentReadWriteLock) which can be used with an ArrayList. Both of these are in mango.containers, which is only in SVN since it't still beta quality- but the List branch of it tends to work pretty well. ~John Demme
Apr 18 2006