Java中的原子性与并发编程总结

问题起源

来自知乎的一个问题引起了我的关注,问题地址是:https://www.zhihu.com/question/42779759

在java doc 中 https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible.
求教各位大神,这个在java中怎么发生这个错误?

我认为该问题的实质是,java中的原子性操作并不能满足多线程访问共享变量的需求,因此还是要使用synchronize等并发手段来进行多线程间的共享变量访问。

原子性和可见性

首先给出两个定义:原子性和可见性。
原子性:In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn’t happen at all. No side effects of an atomic action are visible until the action is complete.简单的说,原子性的操作就是不可被中断的操作,这个操作要么还未开始,要么全部完成。
可见性:可见性是指,一个线程对变量的修改,另一个线程能够立即看到。

原子性操作的分类

Java中的原子性操作,我将其总结为四类:

  1. 原始类型:除long和double意外的原始类型的简单读取、写入操作;所谓简单写入,是指i=1这种赋值操作,而i++不是简单写入;
  2. volatile:使用volatile修饰的变量的简单读取、写入操作;同样的,volatile int i的i++操作不是简单写入;
    3.原子类: java.util.concurrent.atomic包中各种原子类(例如AtomicInteger、AtomicBoolean)的读取、写入操作,注意incrementAndGet这种自增操作具有原子性;
  3. 并发锁:使用synchronize或者Lock进行限定的并发锁,其中的代码都具有原子性。

分析

我对这四种类型就原子性、可见性和性能进行了分析,给出如下表格:(我将i++定义为“自增操作”)

类型原子性简单读写的原子性和可见性自增操作的原子性和可见性复杂代码的原子性和可见性性能
原始类型YN(无可见性)N(既无原子性也无可见性)N
volatileYYN(无原子性)N较高
原子类YYY难以实现
并发锁YYYY

结论

由上表可得出以下结论:

  1. 原始类型虽然对简单读写保持原子性,但是由于没有可见性,在共享资源被多线程访问时基本无用;
  2. volatile变量可对简单读写保持原子性和可见性,因此在较为极端的情况下可用于共享资源的多线程访问,《Thinking in java》一书中曾经提到“如果要使用volatile来修饰多线程的共享资源,除非该对象中仅有一个域的值能够变化,其赋值时不能引用自身的值,也不能添加一些数值的比较条件”。这种要求实在是太苛刻了,一般的自增操作就会打破此规则。因此volatile在绝大多数情况下仍是不可用的;
  3. 原子类的应用领域则宽广得多,由于原子类可对自增操作保持原子性和可见性,因此常常被用来作为多线程中指示数值的共享资源。且原子类的性能要优于并发锁,毕竟它省去了加锁、解锁过程。
  4. 在除了上面2和3提到的一些特殊情况外,其他时间若多线程要访问共享资源,则最好使用并发锁对资源访问代码进行加锁。

    总结起来就是:在并发编程且访问共享变量时,经常用并发锁,明白时用原子类,尽量不用volatile。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值