synchronized class bugs?

Gregor Mückl gregormueckl at gmx.de
Tue Apr 7 15:18:41 UTC 2020


I've been playing around with synchronized class. My example is 
the following dummy class:

     synchronized class Shared {
     public:
         void increment(int value) {
             //(cast(Shared) this).x += value;
             x += value;
         }

         void decrement(int value) {
             //(cast(Shared) this).x -= value;
             x -= value;
         }

         shared int get() { return x; }

     private:
         int x;
     }

Then I'm calling increment and decrement many times in parallel 
threads so that they *should* cancel out in the end and x should 
be back to 0 at the end. With the implicit synchronization using 
d monitors, this should work.

Bug number 1: dmd doesn't translate this without casting away 
shared:

sharedtest.d(14): Error: read-modify-write operations are not 
allowed for shared variables. Use 
core.atomic.atomicOp!"+="(this.x, value) instead.

The += and -= operators are safe as they are inside locked 
monitors. The emitted code contains calls to d_montiorenter and 
d_monitorexit. The compiler should understand this.

Bug number 2: even when casting away shared, the end result is 
wrong when using multiple threads. Thus, the monitor locking code 
in druntime cannot be correct. It does have an effect, though. 
Omitting synchronized on Shared results in values that are wide 
off the mark. Including it results in small differences. This 
suggests that a memory fence might be missing somewhere.

The observed reality contradicts the documentation in many ways 
and is inconsistent with itself. What is going on here?




More information about the Digitalmars-d mailing list