java并发编程的基础
来源:互联网 发布:塞内加 知乎 编辑:程序博客网 时间:2024/05/20 17:09
0 概述
要编写正确的并发程序,关键问题在于:在访问共享的可变状态时需要进行的正确的管理,即原子操作和内存可见性。我们知道同步代码块和同步方法可以确保原子操作,但是一种常见的误解是认为
synchronized只能用于实现原子操作;同步其实还有另一个重要方面:内存可见性。多线程的环境下,我们希望确保一个线程修改了状态之后对另一个线程是可见的。
1 内存可见性
加锁机制既可以保证可见性,又可以保证原子性,而volatile修饰变量只能保证可见性。
public class NoVisibility { private static Test test = new Test(); static class Test { private boolean ready = false; private int number = 0; } private static void run() { new Thread(new Runnable() { @Override public void run() { while (!test.ready) { // System.out.println("number" + test.number); //Thread.yield(); } System.out.println("number" + test.number); } }).start(); } public static void main(String[] args) throws Exception { run(); //确保子线程已经启动 Thread.sleep(1000); test.number = 2; test.ready = true; }}
可以看到如果test是volatile的话线程可以正常结束。
但是如果test不是volatile的话,线程将很大可能一直无法结束,因为没有volatile修饰的话test.ready一直读的是缓存(线程中工作内存),而非主存值,除非cpu有空才会去重新获取test.ready的值,比如在循环体内释放CPU执行资格或者执行一个复杂操作new个对象sysout以下什么的。
2 先行发生原则
先行发生是java内存模型中定义的两项操之间的偏序关系,如果说操作A先行发生于B操作,其实就是说在发生B操作之前,操作A产生的影响能被B观察到,这个影响包括修改了内存共享变量、发送了消息、调用方法等。下面是java内存模型下一些“天然的”先行发生关系,这些先行发生关系无线任何同步器协助就已经存在,可以在编码中直接使用。如果两个操作之间不在此列,并且无法从下列规则推导出来的话,它们就没有顺序性保障,虚拟机就可以对它们随意的重排序。
- 程序次序规则(Program Order Rule):在一个线程内,按照程序代码顺序,书写在前面的代码先行发生于书写后面的代码。
- 管程锁定规则(Monitor Lock Rule)一个unlock 操作先行发生后面对同一个锁lock操作。
- volatile 变量规则(Volatile Variable Rule)对一个volatile变量的写操作先行发生于后面这个变量的读操作。
- 线程启动规则(Thread Start Rule)Thread对象的start() 方法先行发生于此线程的的每一个动作。
- 线程终止规则(Thread Termination Rule)线程中的所有操作都先行发生于对此线程的终止检测,可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。
- 线程中断规则(Thread Interruption Rule)对线程Interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件发生,可以通过Thread.isInterrupted()方法检测到是否发生中断。
- 对象终结规则(Finalizer rule)一个对象的初始化完成,先行发生于它的finalize()方法的开始。
- 传递性(Transitivity)如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出A先行发生于操作C的结论。
深刻理解java内存模型先行发生关系,对于编写正确的并发程序有着很大指导意义。
参考文献
[1] 深入理解java 虚拟机(第二版),周志明著
[2]java 并发编程实战
- java并发编程的基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java 并发编程 基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程:并发基础概念
- java并发编程——并发基础
- 《Java并发系列》0.并发编程基础
- Java并发编程 基础概念
- Java 并发编程 基础 一
- java并发编程-基础原理
- 【Java并发编程】一.基础
- Java并发编程(二)--java线程安全的一些基础
- mybatis和Spring的整合,逆向工程
- 1073. Scientific Notation (20)
- Java实现数组动态输入
- win8下使用VM12安装OS X10.12虚拟机
- Kubernetes API分类汇总
- java并发编程的基础
- 1084. Broken Keyboard (20)
- 【Android】 获取系统时间以及时间与字符串时间的转换以及时间的比较从而设置软件失效时间
- centos 网络配置
- C出错集
- 变量声明和定义的区别
- 3.spring的EL表达式
- React Native
- 开发 Flask 站点(2)—— 模板的渲染