java synchronized具有禁止重排序功能
2017-09-15 11:27
627 查看
1.结论
我们知道volatile关键字具有禁止指令重排序的功能,而且能保证可见性,但不能保证原子性。synchronized关键字则不仅仅能保证可见性,还能保证原子性,那么synchronized关键字是否像volatile那样具有禁止指令重排序的功能呢?答案是肯定的,synchronized具有禁止重排序功能。2.论据出处
查找国内文档,发现基本对synchronized的描述很少提及禁止重排序的问题,大多都是在说原子性。于是查阅了国外的技术文档,其中举例说明了synchronized具有禁止重排序功能:class Test { static int i = 0, j = 0; static void one() { i++; j++; } static void two() { System.out.println("i=" + i + " j=" + j); } }
当有两个线程同时不断的分别执行one()和two()方法,会出现有时j的值比i的值大的情况,说明j++有时在i++之前执行。
但当将以上的类修改为下面时:
class Test { static int i = 0, j = 0; static synchronized void one() { i++; j++; } static synchronized void two() { System.out.println("i=" + i + " j=" + j); } }
也就是使用synchronized关键字修饰方法one和two后,则不会出现j大于i的情况,也正说明了synchronized具有禁止代码重排序功能。
3.验证
以下为完整的不使用synchronized修饰的代码:package sort; public class Test1 { public static void main(String[] args) { MyThread1 thread1 = new MyThread1(); thread1.start(); MyThread2 thread2 = new MyThread2(); thread2.start(); } } class Test { static int i = 0 4000 , j = 0; static void one() { i++;j++; } static void two() { System.out.println("i=" + i + " j=" + j); } } class MyThread1 extends Thread { @Override public void run() { while (true) { Test.one(); } } } class MyThread2 extends Thread{ @Override public void run() { while (true) { Test.two(); } } }
截取部分输出为:
··· i=1096461781 j=1096461781 i=1096462439 j=1096462439 i=1096514978 j=1096514985 i=1096515540 j=1096515546 i=1096516081 j=1096516081 i=1096516643 j=1096516642 i=1096517194 j=1096517194 ···
可见确实j++有时候在i++之前执行。
接下来,将上面代码中的第12行也就是对one方法加上synchronized关键字,则输出截取部分如下:
··· i=233354804 j=233354804 i=233355026 j=233355026 i=233355534 j=233355534 i=233355776 j=233355776 i=233356003 j=233356003 ···
不会出现j++比i++先执行的情况。
注意:可能有的同学在此处想对i和j使用volatile修饰,而不使用synchronized,同样达到禁止重排序的功能,但是事实上这里是错误的,因为可能在执行一次two方法过程中,one方法执行了不止一次,two方法在获得i的值后,one方法又执行了,使得j增加了,这样two方法看到的j可能比i大。
那么为什么使用synchronized不会出现这种情况呢,因为synchronized还有另外一个功能, 就是原子性,i++和j++要么一起执行完,要么都不执行,不会出现先i++后,执行了其他代码,过一会再执行j++的情况。
相关文章推荐
- Java synchronized之用法及功能简介
- Extjs + java + ibatis 具有搜索功能的分页组件
- java map实现排序功能
- java之2.封装一类梯形对象Ladder,该类对象具有上底、下底和高的属性,具有初始化梯形的功能、修改上底、下底和高的功能、求周长的功能、求面积的功能。
- java Arrays工具类的 一些功能(搜索,复制,比较相等,覆盖,排序)
- java-集合(6)-TreeSet,HashSet与TreeSet比较,HashMap,TreeMap只有在排序的功能时使用
- Java 字符串列表拼音排序功能类
- JAVA之.封装一类圆形对象Circle,该类对象具有半径的属性,具有初始化圆的功能、修改半径的功能、求周长的功能、求面积的功能。
- 自定义集合具有排序功能。像datatable
- java中自定义锁实现synchronized功能
- java中List的排序功能的实现
- 【状态机】使用JAVA实现的具有分布式调度功能的状态机
- Java中使用Comparable和Comparator实现字段排序功能
- JAVA写的多线程下载程序,并具有断点续传功能
- DataGrid同时具有分页和排序功能及注意点
- 基于JAVA的图书数据库管理-具有新增,修改,删除,查询功能
- Java实现拖拽列表项的排序功能
- 使用该JavaBean可以将数据在JSP页面中以表格的形式显示出来,并具有动态排序、动态生成查询、自动分页功能
- java第七周实验封装一类对象English,该类对象具有一种功能printEnglish输出英文字母表。再封装一类对象Greek,该类必须是English的子类,该类对象不仅可以调用方法printE
- java实现单链表的初始化,创建,删除,插入,查找,排序,同项删除,退出等功能