digitalmars.D.learn - Thread synchronization
- JohnC (25/25) Nov 29 2006 What's the recommended way to guard static variables?
- Sean Kelly (6/37) Nov 29 2006 They're all safe. Since #1 is in a static method, it will synchronize
- xs0 (5/42) Nov 30 2006 I think the first one synchronizes only on the statement itself, so
- Matthew Wesley (16/61) Jan 03 2007 Perhaps I am misunderstanding the synchronized specification, as none
- Sean Kelly (102/163) Jan 03 2007 This is correct. Given:
What's the recommended way to guard static variables? 1) synchronized by itself? static Object getObj() { synchronized { return sharedVar; } } 2) synchronized on classinfo? static Object getObj() { synchronized (typeof(sharedVar).classinfo) { return sharedVar; } } 3) synchronized on a static Object instance? static this() { syncLock = new Object; } static Object getObj() { synchronized (syncLock) { return sharedVar; } } I've seen all these patterns used. Are they all safe? Cheers, John.
Nov 29 2006
JohnC wrote:What's the recommended way to guard static variables? 1) synchronized by itself? static Object getObj() { synchronized { return sharedVar; } } 2) synchronized on classinfo? static Object getObj() { synchronized (typeof(sharedVar).classinfo) { return sharedVar; } } 3) synchronized on a static Object instance? static this() { syncLock = new Object; } static Object getObj() { synchronized (syncLock) { return sharedVar; } } I've seen all these patterns used. Are they all safe?just specifies a separate static object on which to synchronize. But since it's static, you'll get the same effect. Sean
Nov 29 2006
Sean Kelly wrote:JohnC wrote:I think the first one synchronizes only on the statement itself, so while only one getObj can execute concurrently, it doesn't guard against a similar setObj().. xs0What's the recommended way to guard static variables? 1) synchronized by itself? static Object getObj() { synchronized { return sharedVar; } } 2) synchronized on classinfo? static Object getObj() { synchronized (typeof(sharedVar).classinfo) { return sharedVar; } } 3) synchronized on a static Object instance? static this() { syncLock = new Object; } static Object getObj() { synchronized (syncLock) { return sharedVar; } } I've seen all these patterns used. Are they all safe?just specifies a separate static object on which to synchronize. But since it's static, you'll get the same effect.
Nov 30 2006
On Thu, 30 Nov 2006 13:04:48 +0100 xs0 <xs0 xs0.com> wrote:Sean Kelly wrote:Perhaps I am misunderstanding the synchronized specification, as none of these methods seem safe to me. When I read that "Synchronized allows only one thread at a time to execute ScopeStatement" from http://www.digitalmars.com/d/statement.html#SynchronizedStatement, that seems to me that only the return statement is protected in any of these cases, while any modification of the returned object is unsynchronized. On a related note,, the specification says that "where Expression evaluates to an Object reference, allows only one thread at a time to use that Object to execute the ScopeStatement." Doesn't this mean that there is no way to synchronize separate critical sections? For example, two or more critical sections that would block on the same mutex in a C environment.JohnC wrote:I think the first one synchronizes only on the statement itself, so while only one getObj can execute concurrently, it doesn't guard against a similar setObj().. xs0What's the recommended way to guard static variables? 1) synchronized by itself? static Object getObj() { synchronized { return sharedVar; } } 2) synchronized on classinfo? static Object getObj() { synchronized (typeof(sharedVar).classinfo) { return sharedVar; } } 3) synchronized on a static Object instance? static this() { syncLock = new Object; } static Object getObj() { synchronized (syncLock) { return sharedVar; } } I've seen all these patterns used. Are they all safe?synchronize on the ClassInfo object, just like you're doing which to synchronize. But since it's static, you'll get the same effect.
Jan 03 2007
Matthew Wesley wrote:On Thu, 30 Nov 2006 13:04:48 +0100 xs0 <xs0 xs0.com> wrote:This is correct. Given: synchronized(obj) { ... } You can consider the opening brace of the synchronized block to be equivalent to a mutex lock operation where obj is the mutex being locked. Exiting the scope of a synchronized block by any means releases the lock.Sean Kelly wrote:Perhaps I am misunderstanding the synchronized specification, as none of these methods seem safe to me. When I read that "Synchronized allows only one thread at a time to execute ScopeStatement" from http://www.digitalmars.com/d/statement.html#SynchronizedStatement, that seems to me that only the return statement is protected in any of these cases, while any modification of the returned object is unsynchronized.JohnC wrote:I think the first one synchronizes only on the statement itself, so while only one getObj can execute concurrently, it doesn't guard against a similar setObj().. xs0What's the recommended way to guard static variables? 1) synchronized by itself? static Object getObj() { synchronized { return sharedVar; } } 2) synchronized on classinfo? static Object getObj() { synchronized (typeof(sharedVar).classinfo) { return sharedVar; } } 3) synchronized on a static Object instance? static this() { syncLock = new Object; } static Object getObj() { synchronized (syncLock) { return sharedVar; } } I've seen all these patterns used. Are they all safe?synchronize on the ClassInfo object, just like you're doing which to synchronize. But since it's static, you'll get the same effect.explicit. In all cases however, the programmer is responsible for locking all related functions on the proper object.On a related note,, the specification says that "where Expression evaluates to an Object reference, allows only one thread at a time to use that Object to execute the ScopeStatement." Doesn't this mean that there is no way to synchronize separate critical sections? For example, two or more critical sections that would block on the same mutex in a C environment.Well, these two functions lock on the same mutex: class C { void f1() { synchronized { ... } } void f2() { synchronized { ... } } static void f3() { synchronized { ... } } static void f4() { synchronized { ... } } } C val = new C; // f1 and f2 are mutually exclusive val.f1(); val.f2(); // f3 and f4 are mutually exclusive val.f3(); val.f4(); In this case, the mutex used for f1 and f2 is the object monitor for val, while the mutex used for f3 and f4 is the object monitor for C. This is equivalent to: class C { Object lock; static Object s_lock; this() { lock = new Object; } static this() { s_lock = new Object; } void f1() { synchronized(lock) { ... } } void f2() { synchronized(lock) { ... } } static void f3() { synchronized(s_lock) { ... } } static void f4() { synchronized(s_lock) { ... } } } C val = new C; // f1 and f2 are mutually exclusive val.f1(); val.f2(); // f3 and f4 are mutually exclusive val.f3(); val.f4(); Does that help? Sean
Jan 03 2007