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