以战养战,边学边练,方有所成
volatile轻量级的同步机制,保证可见性,不保证原子性,禁止指令重排
今天就分析一下volatile的关键字,内存可见性,在讲这个之前,我们来看一下,线程是怎么去处理数据的,我们都知道线程是cpu调度的单位,每个线程都是稀缺资源,创建线程会消耗cpu缓存和cpu运算资源,cpu在创建线程之后,线程具有自己的工作空间,java中的变量都是保存在主内存中,如果线程需要操作主内存,那么就需要copy一份变量到自己的工作空间中,进行修改变量操作,操作完,再把操作后的数据写入到主内存,jmm就是控制线程和主内存的变量输入和输出操作,如果这个变量被多个线程操作,当一个变量操作完,如果没有内存可见性的操作,其他线程是不知道该变量被修改了
总结:线程修改变量副本拷贝,发送给主线程,如果变量加了volatile,立马通知给其他线程该变量修改完成
原子性:保证数据完整一致性,中间过程不可被分割,要么成功,要么失败,没有原子性,有可能写覆盖
指令重排序:必须满足数据依赖性,计算机在执行程序时,为了提高性能,对编译器优化重排,指令并行执行,内存系统重排
禁止指令重排:通过插入内存屏障指令,禁止在内存屏障前后的指令执行重排序优化,避免线程执行乱序的情况
yield线程中的关键字,让出线程执行,让其他线程在准备中(Runnable),之后一起执行,Thread.activeCount(),一个程序运行必须有2个或以上线程,类线程和gc线程
解决原子性问题:
- 加sync锁
- 如果是变量可以使用AtomicInteger
private static volatile SingletonDemo singletonDemo = null; /** * 双端检锁 * @return */ private static SingletonDemo getSingleton(){ if (singletonDemo == null){ synchronized (SingletonDemo.class){ if (singletonDemo == null){ singletonDemo = new SingletonDemo(); } } } return singletonDemo; }