我被告知以下代码示例存在数据竞争条件(当然假设是多线程):
class C {
private int x = 0;
private int y = 0;
void f() {
x = 1;
y = 1;
}
void g() {
int a = y;
int b = x;
assert(b >= a);
}
}
然而,我被告知以下“修复”没有数据竞争:
class C {
private int x = 0;
private int y = 0;
void f() {
synchronized(this) { x = 1; }
synchronized(this) { y = 1; }
}
void g() {
int a, b;
synchronized(this) { a = y; }
synchronized(this) { b = x; }
assert(b >= a);
}
}
可以理解,上面的例子还有其他问题,但我只想知道为什么第二个代码块没有竞争条件。同步每个赋值语句如何消除数据竞争条件?一次只同步一个赋值语句有什么意义?
澄清一下,数据竞争是这样定义的:
数据竞争:同时读/写或同时写/写
内存位置
最佳答案
在第一个示例中,data 竞争条件将通过断言失败而被注意到。
这怎么可能呢? y > x 应始终为假,如 y
写在x
之后并在 x 之前阅读。
即使你考虑所有的交错
Thread 1 Thread 2
----------------------------------
read y
read x
write x 1
write y 1
你应该总是有x <= y
但在安全执行中,如果read v
在执行 write v
期间, 无法保证读取的值。
v is 0
T1 write 1: wwwwwwwww
T2 read : rrrrr
T3 read : rrrrr
在这种情况下,T2 读取的值可以是任何值,例如 42
.同时保证T3读到的值是1。
第一种情况a
和 b
可以是任何东西,所以断言可能会失败。
“修复”保证永远不会发生数据竞争(并发读\写),并且 a
和 b
将始终为 0 或 1。
关于java - 如何避免数据竞争——两个例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20677301/