synchronized class bugs?

IGotD- nise at nise.com
Tue Apr 7 16:11:12 UTC 2020


On Tuesday, 7 April 2020 at 15:18:41 UTC, Gregor Mückl wrote:
> 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?

Correct me if I'm wrong, aren't all synchronized classes 
protected with a mutex. In this case atomic operations are 
pointless as all methods are protected by the mutex anyway.



More information about the Digitalmars-d mailing list