我有一个类如下
public MyClass{
Boolean flag = false;
public Boolean getflag(){
synchronized(flag){
//BLOCK 1
return flag;
}
}
public Boolean setflag(){
synchronized(flag){
//BLOCK 2
this.flag = flag;
}
}
}
这两种方法都是在对象标志上同步的。现在我的疑问是两个不同的线程是否可以同时执行同步块(synchronized block)(1&2)。 会出现以下情况吗? 1)线程1正在设置标志值,线程2同时获取其值?
最佳答案
是的,可以。请注意,您正在同步您正在设置的同一对象。因此,setter 可以将对象引用更改为不同的对象,然后 getter 可以在新对象上同步,而 setter 仍在同步块(synchronized block)内。
但还有更多:flag
(通常)是对系统范围单例 Boolean.TRUE
和 Boolean.FALSE
之一的引用>,因此(至少在理论上)可以在类(class)之外锁定这些内容,即使不以任何方式引用您的类(class)。在这种情况下,您可能会陷入僵局,并且很难找出原因。
(另请注意,当前形式的代码是错误的,因为 setter 没有参数,因此 this.flag = flag
将引用分配给自身 - 但上面我假设您是认真的表现得像一个普通的 setter :)
解决方法是使用专用的私有(private)最终
锁对象(如果您想绝对确保外部没有人可以同步您在类中使用的同一个锁 - 我想您的初衷是):
public MyClass{
private final Object lock = new Object();
private Boolean flag = false;
public Boolean getflag(){
synchronized(lock){
//BLOCK 1
return flag;
}
}
public void setflag(Boolean flag){
synchronized(lock){
//BLOCK 2
this.flag = flag;
}
}
}
如果您不太担心内部使用的同一个锁上的其他同步,您可以简单地使您的方法同步
(在这种情况下,它们锁定this
) >).
关于java - 关于线程安全代码的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6926295/