提问人:Mohammad Karmi 提问时间:10/29/2023 最后编辑:Mohammad Karmi 更新时间:10/30/2023 访问量:76
同步块的对象参数是否保证可见性 同步 Java
Are object parameters of synchronized block guranteed visibilty Synchronized Java
问:
对于以下情况,我找不到答案:
public class Example {
int a=0;
public synchronized void method(Object x){
a++;
x.value=x.value+1;
}
}
我知道 happens-before 关系是为同一个对象锁建立的,所以所有内容都应该写入内存(但不确定这里的所有内容是否都包括对 x 的更改),
我的问题:如果对象 X 使用相同的锁,是否保证对其他线程可见?( lock 在示例对象上,但不在 x 本身上)
答:
0赞
Stephen C
10/30/2023
#1
如果对象使用相同的锁,则是否保证对其他线程可见?
x
是的,但这可能没有用。
首先,我需要将您的示例代码转换为可编译的内容,并可用于说明您的问题。
public class Example {
int a = 0;
public synchronized void method(X x){
a++;
x.value = x.value+1;
}
}
public class X {
int value;
}
然后,场景如下:
创建 和 的实例并将其传递给两个线程 A 和 B。
Example
Shared
线程 A 使用公共实例进行调用。
example.method(x)
一段时间后,线程 B 使用通用实例进行调用。
example.method(x)
线程 A 在实例上释放互斥锁与线程 B 获取互斥锁之间将存在 happen before 关系。当我们将此与 happens before 关系相结合时,我们将得到一个保证Example
method
- 任一线程 B 将看到 A 写入的变量的更新值
value
- 或者它将看到在那之后写入的另一个值。
此外,如果任何代码写入调用外部,或使用不同的实例作为锁,则所有赌注都关闭。并且不能保证如果直接读取另一个线程会看到什么。x.value
method
Example
x.value
总之,有一些有保证的行为,但由于围绕保证的注意事项,很难安全地利用它们。最好执行以下操作之一:
- 直接锁定实例;例如,通过 ) 上的同步方法,或者
X
increment
X
- 隐藏实例,以便仅通过 的(例如)方法操作它们。
X
synchronized
Example
评论
0赞
Mohammad Karmi
10/30/2023
只是为了留在问题的上下文中,发生在关系保证线程修改的所有对象的可见性之前,无论是锁还是任何其他对象,您能确认一下吗?
0赞
Stephen C
10/30/2023
它保证了对共享变量(而不是对象)的内存写入的可见性。正如我所描述的那样,这些保证是完整的,并带有警告。我不会用你正在使用的更宽松的术语来重述它们,因为它是模棱两可的。特别是在您的示例中......这也是如何不编写多线程代码的一个例子!
0赞
Stephen C
10/30/2023
我认为答案是“是”......但它可能是“不”......取决于你对可见性的理解。
0赞
Mohammad Karmi
11/1/2023
可见性意味着:A , B 是使用相同锁定对象的线程。如果线程 A 修改了 synchrnise 块内的任何对象,则块 B 应该对 A 修改的所有对象(包括锁定对象)具有可见性
0赞
Stephen C
11/1/2023
那太模糊/高层次了。实际保证是在读取和写入多个线程可访问的变量的级别。如果你要尝试做一些毛茸茸的事情,涉及访问同步块(或等效块)之外的共享变量,你必须在分析之前,在变量读取和写入的级别上执行这些操作。(国际海事组织)你不能走你正在尝试的心理捷径。但。。。坦率 地 说。。。你不应该这样写代码。它太脆弱/太难理解。
评论
x