volatile二三事1
来源:互联网 发布:网络在线客服的要求 编辑:程序博客网 时间:2024/06/07 04:00
1.主内存和工作内存
每个线程有自己的工作内存(线程栈),在调用主内存(公共内存)变量时,先将变量拷贝到工作内存,然后在私有内存中进行读写,而不是直接操作主内存中的数据。这样在多线程下就会有线程安全问题出现。
内存见的交互操作如下图,下面8个是原子操作(lock unlock read load use agsin store write)当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。
2.volatile的作用:强制从公共堆栈(主内存)中取得变量的值,而不是从工作内存(私有线程栈)中获得该变量的值
3.下面的例子
一旦运行在-server服务器模式中的64bit的JVM上回出现死循环,“线程停止了”永远不会输出,private boolean isRunning=true存储在线程栈和主内存中,在-server服务器模式下,为了线程效率,一直在线程栈中取得变量isRunning的值,而该值为true,而代码t.set(false)虽然被执行,但更新的却是主内存中的isRunning,所以-server模式下一直死循环。
也就是线程栈和主内存中的数据不一致导致的,解决办法是volatile,强制从主内存中取值
/** * @Title: Run.java * @Package volatile1 * @Description:volatile相关* @author LingLee * @date 2017年3月23日 下午4:23:53 * @version V1.0 */ package volatile1;class T1 extends Thread{private boolean isRunning=true;//存储在主内存和工作内存中public void run(){System.out.println("进入run了");while(isRunning){}System.out.println("线程被停止了");}public void set(boolean isRunning){this.isRunning=isRunning;}}/** * @Title: Run * @Description: TODO(用一句话描述该文件做什么) */public class Run {public static void main(String[] args){try{T1 t1=new T1();t1.start();Thread.sleep(1000);t1.set(false);System.out.println("已经复制为FALSE");}catch(Exception e){e.printStackTrace();}}}
进入run了线程被停止了已经复制为FALSE
4.可见性(final synchronized volatile)
volatile的使用,jvm只保证了从主内存加载到线程栈中的值是最新的,当一个线程修改了变量的值,新值对于其他线程来说是可见性。如果volatile使用得当,会比synchronized的效率高,因为它不用进行线程见的上下文切换和线程调度,但是现在synchronized随着JDK的新版本,效率得到很大提升。
5.volatile和synchronized比较
(1)volatile是轻量级同步实现,性能更好一些,但是volatile修饰的是变量,而synchronized修饰的是方法和代码块
(2)多线程访问volatile变量不会阻塞,因为volatile在访问变量时都是从主内存中加载最新的值,而synchronized会阻塞。
(3)volatile会保证可见性有序性但不保证原子性,synchronized保证可见性有序性也保证原子性,因为它维持了主内存和线程栈的数据同步。
(4)volatile和synchronized都保证了不可重排序
(5)volatile解决的是多线程间变量的可见性,而synchronized解决的是多线程访问资源的同步性
6、原子性、可见性、有序性
(1)volatile不具有原子性,synchronized和一些AtomicInteger原子类具有原子性
(2)volatile、final、synchronized具有可见性,当线程修改一个共享变量的值,其他线程能够看到。首先volatile每次修改变量都是刷新主内存中的值,并读取主内存的值。final是一旦完成初始化,就不可改变,所以对于其他线程也是可见的。
(3)volatile禁止指令重排序,在指令上添加很多内存屏障,而synchronized一个变量在同一时刻只允许一条线程拥有对象锁。所以具有的有序性,即线程内表现为串行的语义。
- volatile二三事1
- volatile 变量1
- 详解volatile(1)
- 并发编程1-volatile
- volatile
- volatile
- Volatile
- volatile
- volatile
- volatile
- volatile
- volatile
- volatile
- Volatile
- volatile
- volatile
- volatile
- volatile
- 无限循环滚动,从右到左,一次一条
- 获得IntelliJ IDEA激活码的方法
- 选择一个单选按钮,其他文本框或下拉框disable掉
- 为什么MYSQL要设定用UTF8MB4编码 UTF8MB4_UNICODE_CI
- MySQL基础数据库和表操作
- volatile二三事1
- 选择结构
- [Codeforces285E]Positions in Permutations(dp+容斥原理+组合数学)
- 技术点详解---L2TP VPN
- 信息课日常
- 发布开源Library到JCenter
- javascript变声声明提前
- 私有通讯协议
- 执行应用程序出现: No such file or directory