三网合一网站远吗网店推广常用的方法
文章目录
- 与synchronized的区别
- 保证可见性
- 不加volatile,死循环
- 不保证原子性
- 禁止指令重排
- 单例模式DCL使用到volatile
与synchronized的区别
- volatile是线程同步的轻量级实现,性能比synchronized好
- volatile只能修饰变量,synchronized可以修饰方法和代码块
- volatile不会发生阻塞,synchronized可能会发生阻塞
- volatile保证数据可见性,不保证原子性,synchronized都保证
- volatile只要用于解决变量在多个线程之间的可见性,synchronized解决的是多个线程之间访问资源的同步性
保证可见性
不加volatile,死循环
import java.util.concurrent.TimeUnit;public class VolatileDemo {int i = 0;public static void main(String[] args) {VolatileDemo volatileDemo = new VolatileDemo();new Thread(()->{try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}volatileDemo.i=100;},"a").start();while (volatileDemo.i==0){}System.out.println(volatileDemo.i);}
}
不保证原子性
public class VolatileDemo {volatile int i = 0;public static void main(String[] args) {VolatileDemo volatileDemo = new VolatileDemo();for (int i = 0; i < 20; i++) {new Thread(() -> {for (int j = 0; j < 10000; j++) {volatileDemo.i++;}}, String.valueOf(i)).start();}while (Thread.activeCount()>2){Thread.yield();}System.out.println(volatileDemo.i);}
}
禁止指令重排
volatile实现禁止指令重排优化,从而避免多线程环境下程序出现乱序执行的现象。
先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:
- 保证特定操作的执行顺序
- 保证某些变量的内存可见性
由于编译器和处理器都能执行指令重排优化。如果在指令之间插入一条memory barrier则会告诉编译器和CPU,不管什么指令都不能和这条memory barrier指令重排,也就说通过插入内存屏障禁止在内存屏障前后的指令执行重排优化,内存屏障的另一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这些数据的最新版本。
单例模式DCL使用到volatile
public class SingletonDemo {private static volatile SingletonDemo instance;private SingletonDemo(){System.out.println(Thread.currentThread().getName()+"\t 构造方法");}/*** 双重检测机制* @return*/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 = 1; i <=10; i++) {new Thread(() ->{SingletonDemo.getInstance();},String.valueOf(i)).start();}}
}