java - 在对象 Y 上定义的同步块中访问对象 X 是否安全?
问题描述
如果在同步方法或块中访问对象的状态是安全的,那么这个问题就有了答案。我的问题:在同步块中访问对象 X 是否安全,其中同步块位于另一个对象 Y 上,并且 X 存在多个编写者线程?
public class X{
private int value = 0;
/** set method will be invoked by multiple threads**/
public void set(int v){
this.value = v;
}
public int value(){
return value;
}
}
public class Tester{
private final Object Y = new Object();
public void test(X x){
synchronized(Y){
System.out.println(x.value()); // is it guaranteed that x.value will be read from memory and not from the current thread's cache ?
}
}
}
我知道在其上定义了同步块的对象的状态是可以安全访问的,不需要 volatile,但是如果同步块是在另一个对象上定义的呢?
解决方案
海事组织你问错了问题。Java 内存模型不关心对象和类。它只谈论变量的可见性。
块的可见性规则synchronized(o)
非常简单:一个线程在离开块之前对任何变量所做的任何事情都保证在另一个线程随后进入同一实例上的synchronized(o)
块之后对任何其他线程都是可见的。synchronized
o
所以,在你的例子中,如果你有一些X my_x
,并且一些线程 A 这样做:
synchronized(Y) {
my_x.set(55);
}
然后当其他线程 B 随后调用tester.test(my_x)
时,线程 B 将看到线程 A 存储的值。
另一方面,如果线程 A在my_x.set(...)
没有同步 on的情况下调用Y
,那么 Java 不会承诺线程 B 何时会看到更改。
注意:您的程序通过使锁对象成为类Y
的private
成员Tester
,同时使test(X)
函数public
. 这实际上是在请求您(或其他一些程序员)犯错误,即调用由另一个未锁定的线程设置的tester.test(some_random_X)
位置。some_random_X
Y
推荐阅读
- azure - 如何使用新值更新 AzureGroupDeployment?
- mocha.js - 摩卡测试注销控制器抛出无效的用户名
- html - Theming Bootstrap(4) 在 SCSS 中使用 CSS Vars
- aws-glue - AWS Glue 空值作为字符串插入 RDS
- c++ - Cppcheck 忽略 -i 并在干净构建后检查所有文件
- dataframe - 在 PySpark 的同一 agg 中的另一列上使用 agg 中生成的列
- kotlin - 使用 mokito 的间谍时 lambda 中缺少数据
- excel - Excel - 单元格颜色更改时的刷新/运行功能
- node.js - 将 js 响应返回对象表示为字符串
- sql - R 使用 dbplyr 从 SQL Server 复制