www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Some thoughts on the “synchronized” statement

reply BCS <BCS_member pathlink.com> writes:
The synchronized statement makes sure that one block of code is not executed by
more than one thread at the same time. Is there any way to extend this to two
blocks? For example, make sure that at any one time only Foo() or Bar() is
executing but not both.

int  A;

Foo()
{
A = 1;
DoSomthingWithA();
}

Bar()
{
A = 2;
DoSomthingElseWithA()
}

I can see use for this in a collection object to make sure that only one thread
is changing data at any given time.

Another closely linked idea would be to have several levels of protection, e.g.
any number of “low” block can execute but only if no “high” block are running or
waiting. 

One other thought on sync blocks, how about an else that gets run instead of
just blocking.
Jul 16 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dbbso6$275s$1 digitaldaemon.com...
 The synchronized statement makes sure that one block of code is not 
 executed by
 more than one thread at the same time. Is there any way to extend this to 
 two
 blocks? For example, make sure that at any one time only Foo() or Bar() is
 executing but not both.

 int  A;

 Foo()
 {
 A = 1;
 DoSomthingWithA();
 }

 Bar()
 {
 A = 2;
 DoSomthingElseWithA()
 }

int A; Object lock; static this() {lock = new Object;} Foo() { synchronized(lock) { A = 1; DoSomthingWithA(); } } Bar() { synchronized(lock) { A = 2; DoSomthingElseWithA() } }
 I can see use for this in a collection object to make sure that only one 
 thread
 is changing data at any given time.

 Another closely linked idea would be to have several levels of protection, 
 e.g.
 any number of "low" block can execute but only if no "high" block are 
 running or
 waiting.

I'm not sure what you mean here.
 One other thought on sync blocks, how about an else that gets run instead 
 of
 just blocking.

Do you mean it gets repeatedly run after trying to acquire the lock? For fancy behavior like that you can use the port of the Java concurrent package at http://home.comcast.net/~benhinkle/locks/locks.html. The Lock interface supports a "tryLock" method with optional timeout.
Jul 16 2005
parent reply BCS <BCS_member pathlink.com> writes:
In article <dbc2u5$2b7o$1 digitaldaemon.com>, Ben Hinkle says...
int  A;
Object lock;
static this() {lock = new Object;}
Foo()
{
synchronized(lock) {
A = 1;
DoSomthingWithA();
}
}

Bar()
{
synchronized(lock) {
A = 2;
DoSomthingElseWithA()
}
}

I haven’t tried that, but from what the reference says ("synchronized allows only one thread at a time to execute [the] Statement.") I would expect that two different synchronized blocks could both be executed with the same object at the same time (if this is not the case, than the reference is ambiguous or wrong).
 I can see use for this in a collection object to make sure that only one 
 thread is changing data at any given time.

 Another closely linked idea would be to have several levels of protection, 
 e.g. any number of "low" block can execute but only if no "high" block are 
 running or waiting.

I'm not sure what you mean here.

I’m thinking of a sort of read-only vs. write access scenario. Any number of reads can safely happen at the same time as long as no writes are happening but only one write can safely happen at any given time. This might be expressed explicitly as read vs. write or maybe in some other from.
 One other thought on sync blocks, how about an else that gets run instead 
 of
 just blocking.

Do you mean it gets repeatedly run after trying to acquire the lock? For fancy behavior like that you can use the port of the Java concurrent package at http://home.comcast.net/~benhinkle/locks/locks.html. The Lock interface supports a "tryLock" method with optional timeout.

Actually, that looks a lot like what I was thinking of. I was just suggesting that kind of thing (or some of it) be made part of the language. Specifically, I was thinking of a non-blocking synchronized, e.g. "If you can get access to this stuff, run this code, else skip it (or run this other code)" synchronized(A) { //do somthing if A isn't in use } else { //do something else if A is in use } This would allow many other construct, a retry with timeout block could be done like this do synchronized(A) { //do something break; } else{} while(NotTimeOut());
Jul 18 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dbgp3v$9ri$1 digitaldaemon.com...
 In article <dbc2u5$2b7o$1 digitaldaemon.com>, Ben Hinkle says...
int  A;
Object lock;
static this() {lock = new Object;}
Foo()
{
synchronized(lock) {
A = 1;
DoSomthingWithA();
}
}

Bar()
{
synchronized(lock) {
A = 2;
DoSomthingElseWithA()
}
}

I haven't tried that, but from what the reference says ("synchronized allows only one thread at a time to execute [the] Statement.") I would expect that two different synchronized blocks could both be executed with the same object at the same time (if this is not the case, than the reference is ambiguous or wrong).

The next sentance in the doc talks about "synchronized(Expression) {...}". To see why it works only one thread at a time can hold an Object's lock. So to make any number of blocks execute one at a time have each one grab a shared Object's lock.
Jul 18 2005
parent reply BCS <BCS_member pathlink.com> writes:
In article <dbgqi0$auh$1 digitaldaemon.com>, Ben Hinkle says...
 I haven't tried that, but from what the reference says ("synchronized 
 allows only one thread at a time to execute [the] Statement.") 


The next sentance in the doc talks about "synchronized(Expression) {...}". 

Quote the next sentance: "... allows only one thread at a time to use that Object to execute THE Statement." Note emphasis. Again the reference is ambiguous or wrong. It seems that, according to the reference, the synchronized(Exp) form of the synchronized statement is block-centric not object-centric (the lock is on the block with respect to the object not on the object it’s self). If I am wrong than the reference should read "... execute _any synchronized_ Statement."
Jul 18 2005
parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dbgs5q$cd6$1 digitaldaemon.com...
 In article <dbgqi0$auh$1 digitaldaemon.com>, Ben Hinkle says...
 I haven't tried that, but from what the reference says ("synchronized
 allows only one thread at a time to execute [the] Statement.")


The next sentance in the doc talks about "synchronized(Expression) {...}".

Quote the next sentance: "... allows only one thread at a time to use that Object to execute THE Statement." Note emphasis. Again the reference is ambiguous or wrong. It seems that, according to the reference, the synchronized(Exp) form of the synchronized statement is block-centric not object-centric (the lock is on the block with respect to the object not on the object it's self). If I am wrong than the reference should read "... execute _any synchronized_ Statement."

Sure - I agree "any" is more clear than "the". To make it even more clear the phrasing could probably be expand to something like "allows only one thread at a time to use that Object to execute any synchronized statement or synchronized object method that synchronize on that Object". But then I'm no writer :-P
Jul 18 2005