我在某个地方读到,每个线程都有自己的共享状态副本,即使我使用同步或锁来修改变量,如何保证更改的状态将被刷新到主内存中,而不是在线程自己的缓存内存中。
我知道不稳定的保证,并证明上述情况是合理的,甚至我知道同步也是合理的。
同步如何保证在主内存而不是线程缓存内存中发生更改值。
Ex螺纹1
synchronized(this)
{
int a = 0;
a = 5;
} ----> the value might got changed in thread's cache memory another thread entering the block could read a value as 0
volatilte int a = 0;
a = 5; ----> another executing thread will read a values as 5发布于 2020-04-15 21:57:15
在考虑java中的多线程代码时,您必须从happens-before的角度进行推理,这是JLS所使用的,也是您应该使用的。句号。
就您的示例而言,您将volatile和synchronized放在一起,就好像它们做了相同的事情--它们没有。即使是您的示例也失败了,因为“其他”线程要查看一个有保证的a = 5,它必须在相同的锁上同步,而您没有同步。jc应激测试证明您是错误的(我会让您知道如何准确地运行这一点)
@JCStressTest
@State
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "SURPRISE")
@Outcome(id = "0, 1", expect = Expect.ACCEPTABLE, desc = "whatever")
@Outcome(id = "0, 0", expect = Expect.ACCEPTABLE, desc = "whatever")
@Outcome(id = "1, 1", expect = Expect.ACCEPTABLE, desc = "whatever")
public class DifferentSynchronizedObjects {
int x, y;
private Object lock = new Object();
@Actor
public void actor1() {
synchronized (lock) {
x = 1;
y = 1;
}
}
@Actor
public void actor2(II_Result r) {
r.r1 = x;
r.r2 = y;
}
} 即使您不理解代码,它的主要“卖点”是:
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "SURPRISE")您可以将其读为:“当您在同步(锁){.}中时,其他线程出现并读取x和y”。这个阅读线程看到了1, 0 (x = 1,y = 0),现在考虑一下它。您在synchronized块中,为什么有些线程读取x = 1和y = 0,难道不是“受保护”吗?不,你没有。如果你运行这个-你会得到1, 0。
编辑以回答注释
您认为您是在保护x和y的通信--但是由于JLS没有提供这样的保证,这是您对事物的理解,这是错误的。就这么简单。您真正得到的唯一保护是,如果您的作者和读者使用相同的锁。
优化器可能会“看到”您只在方法中使用该lock,并将该代码转换为(至少在理论上):
@Actor
public void actor1() {
Object lock = new Object(); // < -- make lock local
synchronized (lock) {
x = 1;
y = 1;
}
}既然lock现在是一个方法的局部,那么拥有它又有什么意义呢?没有人能够访问它,只需将其完全删除。因此,您将得到一个完全不受保护的代码,它执行两个独立的写操作。
结论是:你不遵守JLS给你的规则--做好准备,得到奇怪的结果。
发布于 2020-04-15 18:14:20
如果不使用synchronized关键字(或易失性关键字),就不能保证当一个线程更改与其他线程共享的变量的值时,其他线程可以看到更改的值。不能保证由一个线程保存在CPU寄存器中的变量何时“提交”到主内存,也不能保证其他线程何时“刷新”主内存中保存在CPU寄存器中的变量。
使用synchronized关键字,当线程进入同步块时,它将刷新线程可见的所有变量的值(在同一个锁/对象上)。当线程退出同步块时,对线程可见的变量以及同一锁的所有更改都将被推送/更新到主内存。实际上,它与volatile的工作是一样的。
https://stackoverflow.com/questions/61235213
复制相似问题