java并发

java并发 1.原子性 可见性 有序性原子性synchronized可见性volatilesynchronizedfinal有序性volatilesynchronized2.volatile特性1.防止指令重排序2.线程可见经典使用场景1.DCL单例模式public class Singleton { private volatile static Singleton instance; public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } public static void main(String[] args) { Singleton.getInstance(); } }主要应用了防止指令重排序因为 new Singleton() 非原子操作。jvm会将其分解为多个步骤分配内存空间调用构造函数初始化对象将instance引用指向该内存地址。2.并发开关volatile boolean shutdownRequested; public void shutdown() { shutdownRequested true; } public void doWork() { while (!shutdownRequested) { //代码的业务逻辑 } }使用了线程的可见性特性3.反例public class VolatileTest { public static volatile int race 0; public static void increase() { race; } private static final int THREADS_COUNT 20; public static void main(String[] args) { Thread[] threads new Thread[THREADS_COUNT]; for (int i 0; i THREADS_COUNT; i) { threads[i] new Thread(new Runnable() { Override public void run() { for (int i 0; i 10000; i) { increase(); } } }); threads[i].start(); } // 等待所有累加线程都结束 while (Thread.activeCount() 1) Thread.yield(); System.out.println(race); } }因为race不是原子操作又没有加锁所以并不安全工作线程虽然读取了主内存的数据但是由于操作非原子导致计算之后写回主线程的数据有误3.synchronized1.原子性底层使用了节码指令monitorenter和monitorexit来实现lock,unlock2.可见性同步块的可见性是由“对一个变量执行unlock操作之前必须先把此变量同步回主内存中执行store、write操作”这条规则获得的3.有序性Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性volatile关键字本 身就包含了禁止指令重排序的语义而synchronized则是由“一个变量在同一个时刻只允许一条线程对 其进行lock操作”这条规则获得的这个规则决定了持有同一个锁的两个同步块只能串行地进入。