Doug Lea wrote (and Cliff editted out big chunks):
> The basic idea is that you'd like to allow fusion of blocks locking on
> the same lock. That is:
> synchronized(x) { a(); }
> synchronized(x) { b(); }
> may be transformed into
> synchronized(x) { a(); b(); }
>
> Rule 2: No block may be fused with itself.
>
> T1 T2
> for (;;) { synchronized(x) { a = 1; }
> synchronized(x) {
> if (a != 0) break;
> }
> }
>
> It's clearly a bad idea to transform T1's code to one in which the
> block is fused with itself:
>
> synchronized(x) {
> for (;;) {
> if (a != 0) break;
> }
> }
>
> ... since T1's loop that was previously guaranteed to terminate if T2
> ever reached its assignment can now lockout T2 and livelock T1.
>
> (On the other hand, loop unrollings should be allowed to fuse unrolled
> segments.)
I understand your intent, but "loop unrollings should be allowed to fuse
unrolled segments" looks like it contradicts Rule 2. Fer instance, if one
runs over to SciMarks and looks at the MonteCarlo simulation, one
sees stuff like:
for( int i = 0; i < 1bazillion; i++ ) {
sync(global_lock) {
obtain psuedo random # and update seed under lock
}
simulate_using_psuedo_random_value
}
which one clearly wants to unroll as:
for( int i = 0; i < 1bazillion; i+=2 ) {
sync(global_lock) {
obtain psuedo random # and update seed under lock
}
simulate_using_psuedo_random_value
sync(global_lock) {
obtain psuedo random # and update seed under lock
}
simulate_using_psuedo_random_value
}
then fuse the locks. Or perhaps do unroll-and-jam:
for( int i = 0; i < 1bazillion; i+=8 ) {
for( int j = 0; j < 8; j++ ) {
sync(global_lock) {
obtain psuedo random # and update seed under lock
}
simulate_using_psuedo_random_value
}
}
Now the inner loop is known to be short duration, so fusing the lock
with itself:
for( int i = 0; i < 1bazillion; i+=8 ) {
sync(global_lock) {
for( int j = 0; j < 8; j++ ) {
obtain psuedo random # and update seed under lock
simulate_using_psuedo_random_value
}
}
}
In any case, having a Rule 2 flatly deny fusing a lock with itself isn't what
you really want, since you've already come up with exceptions to it. Instead
I like your fairness guarentee rule. And hoisting a lock outside a huge
(but finite) loop should be allowed but stupid - it falls under the "quality of
implementation" rules that C compilers hit all the time.
Cliff
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:29 EDT