加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 同步,易失性和线程安全

发布时间:2020-12-15 03:01:33 所属栏目:Java 来源:网络整理
导读:我最近正在阅读一些关于 java并发的书.关于线程安全性,如果无法使类不可变,则可以始终通过同步其数据来确保线程安全. 以下类显然不是线程安全的 public class NotThreadSafe { private int value; public void setValue(int value) { this.value = value; }
我最近正在阅读一些关于 java并发的书.关于线程安全性,如果无法使类不可变,则可以始终通过同步其数据来确保线程安全.

以下类显然不是线程安全的

public class NotThreadSafe {
  private int value;

  public void setValue(int value) {
    this.value = value;
  }

  public int getValue() {
    return this.value;
  }
}

然后我可以同步写入,但它仍然不是线程安全的

public class StillNotThreadSafe {
  private int value;

  public synchronized void setValue(int value) {
    this.value = value;
  }

  public int getValue() {
    return this.value;
  }
}

因为我不仅需要同步写入,还需要同步读取

public class ThreadSafe {
  private int value;

  public synchronized void setValue(int value) {
    this.value = value;
  }

  public synchronized int getValue() {
    return this.value;
  }
}

现在问题是,通过使用volatile我可以保证其他线程会看到更新的值,所以这让我觉得这个类应该是线程安全的

public class NotSure {
  private volatile int value;

  public synchronized void setValue(int value) {
    this.value = value;
  }

  public int getValue() {
    return this.value;
  }
}

最后一个类是线程安全的??

解决方法

简短回答:

是的,但在最后一种情况下你甚至不需要同步. setValue唯一能做的就是单个操作,写操作 – 每个操作中的挥发性都是原子的.也就是说,每次写入都是原子的,每次读取都是原子的.

更长的答案:

当然,如果您尝试使用以下模式增加值:

NotSure ns = new NotSure();
int v = ns.getValue();
ns.setValue(v + 1);

…那么这不是线程安全的,因为它涉及对ns.value(读和写)的两个操作,而volatile只给你一个操作的原子性.在这种情况下,即使向getter和setter同步添加也是不够的,因为可以在两个方法调用之间注入操作.

最后一点实际上是声称“你可以通过同步[对象的]数据来确保线程安全”的一个反驳论点.如果您想要一种线程安全的方法来增加NotSure.value,您需要同步整个增量操作,而不仅仅是访问对象的数据.在这种情况下,您需要同步setter,因为它可以在增量方法的操作之间插入它自己. getter仍然不需要同步,因为volatile关键字将确保getter获得预递增或后递增的值.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读