Thread overview
basic concurrency
Apr 18, 2006
Tydr Schnubbis
Apr 18, 2006
Frank Benoit
Apr 18, 2006
Tydr Schnubbis
Apr 18, 2006
Frank Benoit
Apr 18, 2006
kris
Apr 18, 2006
Tydr Schnubbis
Apr 18, 2006
Sean Kelly
Apr 19, 2006
Tydr Schnubbis
Apr 19, 2006
kris
Apr 18, 2006
John Demme
April 18, 2006
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.
April 18, 2006
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.

April 18, 2006
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
April 18, 2006
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.
> 
Putting the array inside a class was what I was thinking about.  Let's 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?
April 18, 2006
> 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.
April 18, 2006
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.
April 18, 2006
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?
April 18, 2006
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
April 19, 2006
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?
> 
It answers the second question I think, but the first one is more important for me to understand the answer to.  But thanks anyway. :)
April 19, 2006
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'.