我有两节课。
一个类只是一个带有get和set synchronized方法的整数值的容器。
public class Sync {
private int dataSync;
public synchronized int getDataSync() {
return dataSync;
}
public synchronized void setDataSync(int data) {
dataSync = data;
}
}
其他课程类似。 它只是一个整数值的容器,其get和set方法没有同步。
public class NotSync {
private int dataNotSync;
public int getDataNotSync() {
return dataNotSync;
}
public void setDataNotSync(int data) {
dataNotSync = data;
}
}
现在我的问题是"保证10个值对所有其他线程可见#34;在run方法结束时。
public class RunSync {
public static void main(String[] args) {
RunSync rs = new RunSync();
rs.run();
}
private NotSync dataNS;
private Sync dataS;
private int data;
public RunSync() {
dataS = new Sync();
dataNS = new NotSync();
}
public synchronized void run() {
data = 100;
dataS.setDataSync(45);
dataNS.setDataNotSync(10);
//Question A: is 10 value guaranteed to be visible to all other
//threads when method exits?
//we are inside a synchronized block aren't we?
//so all writes must be flushed to main memory
}
}
编辑:想象一下还有其他线程。这只是一个快速编写的例子。问题是在同步块完成时确切地保证刷新回主存储器。
EDIT2:根据java内存模型 "只有在某些条件下,才能保证一个线程对字段的更改对其他线程可见。一个条件是写入线程释放同步锁,读取线程随后获取相同的同步锁。
因此,如果另一个线程获得RunSync锁定,是否可以保证在RunSync的NotSync实例中看到10?即使NotSync不受保护?
Edit3:没有确定答案的相关问题。我还在寻找。 What is the scope of memory flushed or published to various threads when using volatile and synchronized?
EDIT4:要简化示例,请从RunSync类
中简化此方法public synchronized void run2() {
dataNS.setDataNotSync(10);
}
当run2退出时,什么都不能保证刷新到主内存?对此的明确答案将回答我的问题。如果否,这意味着只保证刷新锁定成员,并且对其他线程可见,其他线程在RunSync上获取相同的锁定。 答案是无保证。
EDIT5:在这种情况下,断言是否保证为真?
public class RunSync {
public volatile boolean was10Written = false;
public synchronized void run2() {
dataNS.setDataNotSync(10);
was10Written = true;
}
public void insideAnotherThread() {
if(was10Written) {
int value = dataNS.getDataNotSync();
assert value == 10;
}
}
}
答案 0 :(得分:2)
答案是否定的,不保证可见,但可能是。由于10的写入不同步,因此在对同步读取进行排序之前不会发生。
根据java内存模型"只有在某些条件下,才能保证一个线程对字段的更改对其他线程可见。
如果一个线程的写入发生在同步操作之前,则为true。写入10后发生,因此没有可见性保证。
例如,如果您有一个新字段并在写入dataSync
(同步)之前将其写入10,并且您将dataSync评估为45,那么对新字段的写入将是可见的。
答案 1 :(得分:0)
还有什么其他主题?无论如何,你应该看到关键字volatile for start。同步一个方法也不会同步实例变量进行读/写。因此,如果一个线程正在写入,另一个线程可以读取不同的值,因为只有方法是同步的(一次只有一个线程正在设置值,一个正在读取,但是你可以同时读取/写入同一时间