前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Volatile详解

Volatile详解

作者头像
用户5927264
发布2019-09-03 20:05:59
4390
发布2019-09-03 20:05:59
举报
文章被收录于专栏:OSChinaOSChina

1 Volatile详解

代码语言:javascript
复制
package com.shi.jvm;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

class MyData{
	
	volatile int num = 0;
	
	public void addTo60() {
		this.num = 60;
	}
	
	//目前num 是怎加了 volatile 修饰的 :验证不保证原子性
	public void addPlus() {
		num++;
	}
	
	/**
	 * 使用原子整形来保证原子性
	 */
	AtomicInteger atomicInteger = new AtomicInteger();
	public void myAddAtomic() {
		atomicInteger.getAndIncrement();
	}
	
}

/**
 * 1 验证volatile的可见性 : 就是及时通知别的线程该值发生变化了
 * 		1.1. 假如 int num = 0; 没有增加 volatile关键字的修饰
 * 		结果:主线程一直在循环,一直没有收到 num 改变的通知
 *  	1.2. 在  int num = 0 前面增加 volatile关键字
 *  	结果: 在线程1把 num值改变之后 立即收到通知,退出循环
 *  
 * 2 验证volatile 不保证原子性
 * 	 2.1 原子性什么意思?
 * 		不可分割,完整性,也即某个线程正在做具体业务时,中间不可以被加塞或者被分割,
 * 	   	需要整体完整,要么同时成功,要么同时失败
 * 	 2.2 volatile 不保证原子性 验证
 *   	启动20个线程,每个线程自加1000次 看最钟结果
 *   	结果:每次执行的 myData.num 结果都是不一样的 
 *   2.3 为什么?
 *   	原因:num++ 底层是要经过3步操作才完成的
 *   2.4 怎么解决
 *   	(1).在方法中增加 synchronized
 *   	(2).使用 AtomicInteger 来实现原子性
 * @author shiye
 *
 */
public class ValatileTest {

	public static void main(String[] args) {
		ValatileTest.notAtomic();
	}
	
	/**
	 * 1 验证方法的可见性
	 */
	public static void checkSee() {
		MyData myData = new MyData();
		
		//1 启动 1 个新的线程,在这个线程里面改变主线程里面的值
		new Thread( () -> {
			System.out.println(Thread.currentThread().getName() + "\t come in");
			//睡眠3秒
			try {
				TimeUnit.SECONDS.sleep(3);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			myData.addTo60();
			System.out.println(Thread.currentThread().getName() + "\t updated num value:" + myData.num);
		},"AAA").start();
		
		//2 主线程是第2个线程,一直在循环
		while(myData.num == 0 ) {
		}
		
		System.out.println(Thread.currentThread().getName() + "\t mission is over" + myData.num);
	}
	
	
	/**
	 * 2 volatile 验证不是原子性
	 */
	public static void notAtomic(){
		MyData myData = new MyData();
		for (int i = 0; i < 20; i++) {
			//启动20个线程,每个线程自家1000次
			new Thread(() -> {
				for (int j = 0; j < 1000; j++) {
					myData.addPlus();//没有实现原子性
					myData.myAddAtomic();//使用原子整形的方式来实现原子性
				}
			},String.valueOf(i)).start();
		}
		//需要等待上面20个线程全部执行完毕,再看main方法取得最终结果是多少
		while(Thread.activeCount()>2) {
			//剩下俩个线程一个是GC 另一个是main
			Thread.yield();
		}
		System.out.println(Thread.currentThread().getName() + "\t int mission is over : " + myData.num);
		System.out.println(Thread.currentThread().getName() + "\t AtomicInteger mission is over : " + myData.atomicInteger);
	}

}


/**
 * 在多级环境中无法保证指令执行的顺序是按照代码写的顺序执行的,有很多不可测性
 * @author shiye
 *
 */
class ReSortSeqDemo{
	int a = 0;
	boolean flag = false;
	
	public void method01() {
		a = 1;  //语句1
		flag = true; //语句2
	}
	public void method02() {
		if(flag) {
			a = a +5;
			System.out.println("method02 方法提前了 请注意a : " + a);
		}
	}
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档