Java并发编程的三大特性

一.原子性

概念:一个操作或多个操作做为一个整体,要么全部执行并且必定成功执行,要么不执行。简单理解就是程序的执行是一步到位的,而不是分布式的

在java当中,直接的读取操作和赋值(常量)属于原子性操作。对于原本不具有原子性的操作我们可以通过synchronized关键字或者Lock接口来保证同一时间只有一个线程执行同一串代码,从而也具有了原子性。

二.有序性

概念:程序的执行是存在一定顺序的。在Java内存模型中,为了提高性能,编译器和处理器会对程序指令做重排序。在单线程中,重排序不会影响程序的正确性,但在并发编程中,却有可能得出错误的结果。
在这里插入图片描述
在java当中使用volatile关键字来保证一定的有序性
如下表所示是JMM针对编译器制定的volatile重排序规则表:

是否能重排序 操作二 操作二 操作二
操作一 普通读写 volatile读 volatile写
普通读写
volatile读
volatile写

另外也可以用synchronized关键字Lock接口来保证有序性。

三.可见性

概念:在我的理解中,可见性就是指在共享变量被某一个线程修改之后,另一个线程访问的时候能够立刻得到修改以后的值。

普通的、未加修饰的共享变量是不能保证可见性的。我们照样可以通过synchronized关键字和Lock接口来保证可见性,同样也能利用volatile实现。

当一个共享变量被volatile修饰时,就可以保证
1.一个线程修改任意一个共享变量后,其他任何线程再次访问该变量都将获得最新值。
2.不仅是修改以后的值对其余线程可见,修改之前的值仍然具有可见性。

JSR-133 内存模型使用happens-before原则来阐释线程之间的可见性。如果一个操作对另一个操作存在可见性,那么他们之间必定符合happens-before原则:
程序顺序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
监视器锁规则:一个unLock操作先行发生于后面对同一个锁的lock操作。
volatile域规则:对一个变量的写操作先行发生于后面对这个变量的读操作
传递性规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C。

在并发编程中,必须同时保证程序的原子性、有序性和可见性才能够保证程序的正确性。

猜你喜欢

转载自blog.csdn.net/m0_46550452/article/details/107395103