java多线程-线程之间的可见性

java多线程-可见性

(1)定义:一个线程对主内存的修改可以及时的被其他线程观察到
(2)共享变量在线程间不可见的原因:
① 线程交叉执行
② 线程交叉执行结合指令重排序
③ 共享变量没有在更新后的值没有在工作内存与主存之间及时更新
(3)synchronized的两条规定
① 线程释放锁前,必须把共享变量的最新值刷新到主内存当中
② 线程获取锁时,将当前线程的本地内存置为无效,从而使用共享变 量时需要从主内存中重新读取最新的值
(4)volatile通过内存屏障和禁止重排序以及禁止中断优化来实现(从CPU的角度去看)
① 对volatile变量进行写操作时,会在写操作后面加入一条store 屏障指令,将本地内存中的共享变量值刷新到主内存当中;
② 对volatile读变量时,会在读操作前加入一条load屏障指令,从 主内存中读取共享变量;
③ volatile变量在线程每次访问的时候都强迫线程从主内从读取变 量,而当该变量发生变化的时候又会强迫线程将最新的值刷新到主 内存中,这两个操作保证了volatile线程之间的可见性;
④ volatile只是保证了共享变量的可见性,并没有保证volatile修 饰的变量的所有操作都是原子操作。对于被volatile修饰的变量 用于get方法和set方法都是线程安全的;此时相当于在get和set 方法上面添加了synchronized关键字。但是对于非原子操作的就 不是线程安全的方法;
⑤ volatile适合用于作为检查某个状态标记量以判断是否退出循环 和双重检测机制(安全单例模式)
(5)有序性-happens-before原则
1、程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先 行发生于写在后面的操作(虽然虚拟机可能进行了重排序,但是程序 执行的顺序看起来是按照在代码书写的样式执行的。只会对数据不 存在依赖性的指令进行重排序);这条规则只能保障单线程中保持正 确性,而无法在多线程中保持正确性。
2、锁定规则:一个unlock操作先行发生于后面对同一个资源lock的 操作(对一段代码或一个变量,只有锁定了资源的锁先执行了 unlock操 作,下一个线程才有可能执行lock操作。这里需要注 意,当一个锁再一次进入同一个锁的时,这时候是否先执行 unlock还是怎样??)
3、volatile变量规则:对一个变量的写操作先行发生于后面这个变量 的读操作。
4、传递规则:如果操作A先发生于操作B,而操作B又先行发生于操作 C,则可以得出操作A先行发生于操作C
5、线程启动规则:Thread对象的start()方法先行发生于此线程的每 一个动作
6、线程中断规则:对线程interrupt()方法的调用先行发生于被中断 的代码检测到中断事件的发生。(只有执行了中断方法以后才能检测 中断时间的发生)
7、线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我 们可以通过Thread.join()方法结束、Thread.isAlive()的返回 手段检测到线程已经终止执行。
8、对象终结规则:一个对象的初始化完成先行发生于他的finalize() 方法的开始

猜你喜欢

转载自blog.csdn.net/makeliwei1/article/details/80948487