java - 关于线程安全代码的问题

标签 java synchronization thread-safety

我有一个类如下

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.TRUEBoolean.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/

相关文章:

java - 确定哪个线程拥有监视器

android - 使用 dropbox sync API 的 android 应用程序可以使用本地安装的 dropbox 官方应用程序的缓存、文件系统和文件吗?

java - 如何在使用RentrantLock完成所有三个 map 的初始化之前避免读取,并在更新完成后返回更新的 map 集?

c++ 多线程参数问题

C# HTTPWebRequest 多线程

java - 微调器,如果再次选择项目

java - 从@Configuration创建bean定义之后

java - 如何以 FIFO 顺序从文件夹中轮询文件

java - AtomicInteger 类中 addAndGet 的实现

java - 最后在异常处理