修饰符volatile和synchronized的区别联系
来源:互联网 发布:配眼镜测得数据的意思 编辑:程序博客网 时间:2024/06/09 14:28
关键字volatitle的主要作用是使变量在多个线程间可见。关键字volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。
public class RunThread extends Thread { private volatile boolean isRunning = true; public boolean isRunning(){ return isRunning; } public void setRunning(boolean isRunning){ this.isRunning = isRunning; } @Override public void run(){ System.out.println("进入run了"); while (isRunning==true){ } System.out.println("线程被停止了"); }}public class Run { public static void main(String[] args) { try { RunThread thread = new RunThread(); thread.start(); Thread.sleep(1000); thread.setRunning(false); System.out.println("已经赋值为false"); } catch (InterruptedException e) { e.printStackTrace(); } }}输出结果:进入run了已经赋值为false线程被停止了
使用volatile关键字增加了实例变量在多个线程之间的可见性。但volatile关键字最致命的缺点是不支持原子性。下面是synchronized和volatile的比较:
- 关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰变量,而synchronized可以修饰方法,以及代码块。随着JDK新版本的发布,synchronized关键字在执行效率上得到很大提升,在开发中使用synchronized关键字的比率还是比较大的。
- 多线程访问volatile不会发生阻塞,而synchronized会出现阻塞。
- volatile能保证数据的可见性,但不保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步。
- 再次重申一下,关键字volatile解决的是变量在多个线程之间的可见性;而synchronized关键字解决的是多个线程之间访问资源的同步性。
线程安全包含原子性和可见性两个方面,Java的同步机制都是围绕这两个方面来确保线程安全的。
volatile非原子的特性
关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么也就不具备原子性。代码如下:
public class MyThread extends Thread { public volatile static int count; private static void addCount() { for (int i = 0; i < 100; i++) { count++; } System.out.println("count=" + count); } @Override public void run(){ addCount(); }}public class Run { public static void main(String[] args) { MyThread[] myThreads = new MyThread[100]; for (int i = 0; i < 100; i++) { myThreads[i] = new MyThread(); } for (int i = 0; i < 100; i++) { myThreads[i].start(); } }}输出结果:count=8101count=8209count=8209count=8309count=8409count=8509count=8609count=8709count=8809count=8909count=9009count=9109count=9309count=9409count=9409count=9509count=9609count=9709count=9809运行结果值不是10000改代码:
public class MyThread2 extends Thread { public volatile static int count; //注意一定要加synchronized关键字 //这样synchronized与static锁的内容就是MyThread2.class类了 //也就达到了同步的效果了 private synchronized static void addCount() { for (int i = 0; i < 100; i++) { count++; } System.out.println("count=" + count); } @Override public void run(){ addCount(); }}public class Run { public static void main(String[] args) { MyThread2[] myThreads = new MyThread2[100]; for (int i = 0; i < 100; i++) { myThreads[i] = new MyThread2(); } for (int i = 0; i < 100; i++) { myThreads[i].start(); } }}输出结果:count=8000count=8100count=8200count=8300count=8400count=8500count=8600count=8700count=8800count=8900count=9000count=9100count=9200count=9300count=9400count=9500count=9600count=9700count=9800count=9900count=10000
如果在方法private static void addCount()加上synchronized同步关键字,也就没有必要使用volatile关键字来声明count变量了。
关键字volatile的主要使用的场合是在多个线程中可以感知实例变量被更改了,并且可以获得最新的值使用,也就是用多线程读取共享变量时可以获得最新值使用。
关键字volatile提示线程每次从共享内存中读取变量,而不是从私有内存中读取,这样就保证了同步数据的可见性。但这里需要注意的是:如果修改实例变量中的数据,比如i++,也就事i=i+1,则这样的操作其实并不是一个原子操作,也就是非线程安全的。表达式i++的操作步骤分解如下:
- 从内存中取出i的值
- 计算i的值
- 将i的值写到内存中
假如在第2步计算值得时候,另外一个线程也修改i的值,那么这个时候就会出现脏数据。解决的办法其实就是使用synchronized关键字。所以说volatile本身并不处理数据的原子性,而是强制对数据的读写及时影响到主内存的。
阅读全文
0 0
- 修饰符volatile和synchronized的区别联系
- volatile和synchronized的区别和联系
- volatile和synchronized的区别与联系
- volatile和synchronized的区别与联系
- volatile和synchronized的区别与联系
- volatile和synchronized的区别
- volatile和synchronized的区别
- volatile和synchronized的区别:
- volatile和synchronized的区别
- Synchronized和volatile的区别
- volatile和synchronized的区别
- synchronized和volatile的区别
- synchronized和volatile的区别
- volatile和synchronized的区别
- synchronized和volatile的区别
- volatile和synchronized的区别
- volatile和synchronized的区别
- volatile和synchronized的区别
- 实战——session共享(Spring Boot + Spring Session + Redis)
- ZOJ 2112 Dynamic Rankings
- 负载均衡算法
- 字符串:各种奇葩内置--2017/9/3--2
- 下降子序列的个数等于最长上升子序列的长度
- 修饰符volatile和synchronized的区别联系
- bzoj 4995: [Usaco2017 Feb]Why Did the Cow Cross the Road
- 关于热更新的一些分享
- 51Nod-1137-矩阵乘法
- 662. Maximum Width of Binary Tree
- 在Linux里设置用户环境变量的方法
- Selenium TestNG Java环境搭建过程中所遇问题汇总
- 欢迎使用CSDN-markdown编辑器
- MyCat介绍与配置