指当多个线程访问同一个变量时,如果其中一个线程修改了这个变量的值,其他线程能够立即看得到修改的值
验证可见性demo:
import java.util.concurrent.timeunit; class mydata { volatile int number = 0; public void addto60() { number = 60; } } public class volatiledemo { public static void main() { mydata mydata = new mydata(); new thread(() -> { system.out.println(thread.currentthread().getname() + "\t come in"); try { timeunit.seconds.sleep(3); } catch (interruptedexception e) { e.printstacktrace(); } mydata.addto60(); system.out.println(thread.currentthread().getname() + "\t updated number: " + mydata.number); }, "aaa").start(); while (mydata.number == 0) {} system.out.println(thread.currentthread().getname() + "\t mission is over"); } }
结果:
aaa come in main mission is over aaa updated number: 60
原子性:程序中的所有操作是不可中断的,要么全部执行成功要么全部执行失败
不保证原子性正是volatile轻量级的体现,多个线程对volatile修饰的变量进行操作时,会出现容易出现写覆盖的情况(i++)
验证不保证原子性demo:
import java.util.concurrent.timeunit; import java.util.concurrent.atomic.atomicinteger; class mydata { volatile int number = 0; public void addplusplus() { number++; } } public class volatiledemo { public static void main(string[] args) { mydata mydata = new mydata(); for (int i = 0; i < 20; i++) { new thread(() -> { for (int j = 0; j < 1000; j++) { mydata.addplusplus(); } }, string.valueof(i)).start(); } while (thread.activecount() > 2) { thread.yield(); } system.out.println(thread.currentthread().getname() + "\t finally number value: " + mydata.number); } }
结果:
main finally number value: 19109
解决不保证原子性问题:atomic
import java.util.concurrent.timeunit; import java.util.concurrent.atomic.atomicinteger; class mydata { volatile int number = 0; public void addplusplus() { number++; } atomicinteger atomicinteger = new atomicinteger(); public void addatmic() { atomicinteger.getandincrement(); } } public class volatiledemo { public static void main(string[] args) { mydata mydata = new mydata(); for (int i = 0; i < 20; i++) { new thread(() -> { for (int j = 0; j < 1000; j++) { mydata.addatmic(); } }, string.valueof(i)).start(); } while (thread.activecount() > 2) { thread.yield(); } system.out.println(thread.currentthread().getname() + "\t finally number value: " + mydata.number); system.out.println(thread.currentthread().getname() + "\t atomicinteger type,finally number value: " + mydata.atomicinteger); } }
结果:
main finally number value: 19746 main atomicinteger type,finally number value: 20000
指令重排:为了提高程序运行效率,编译器可能会对输入指令进行重新排序,即程序中各个语句的执行先后顺序同代码中的顺序不一定一致。(但是它会保证单线程程序最终执行结果和代码顺序执行的结果是一致的,它忽略了数据的依赖性)
源代码 -> 编译器优化重排 -> 指令并行重排 -> 内存系统重排 -> 最终执行指令
volatile能够实现禁止指令重排的底层原理:
高并发环境下dcl单例模式使用volatile
public class singletondemo { private static volatile singletondemo instance = null; private singletondemo() { system.out.println(thread.currentthread().getname() + "我是构造方法singletondemo()"); } public static singletondemo getinstance() { if (instance == null) { synchronized (singletondemo.class) { if (instance == null) { instance = new singletondemo(); } } } return instance; } public static void main(string[] args) { for (int i = 0; i < 10; i++) { new thread(() -> { singletondemo.getinstance(); }, string.valueof(i)).start(); } } }
juc包下atomicxxx类:原子类atomicxxx中都有一个成员变量value,该value变量被声明为volatile,保证
atomicxxx类的内存可见性,而原子性由cas算法&unsafe类保证,结合这两点才能让atomicxxx类很好地替代synchronized关键字。
public class atomicinteger extends number implements java.io.serializable { // ... private volatile int value; // ... }
如对本文有疑问, 点击进行留言回复!!
android用Popup弹出窗(PopupWindow的使用方式)
ionic3 打包 Could not get resource ‘https://jcenter.bintray.com/com/google/zxing/core/3.2.1/core-3.2.1
NullPointerException: Attempt to invoke virtual method ‘android.content.res.XmlResourceParser androi
网友评论