java并发编程实践 volatile

2 篇文章 0 订阅
1 篇文章 0 订阅

在没有说volatile之前先看看未使用volatile导致问题的情况。例如下面的TestVolatile1编译的时候添加了 -server。则程序不会终止.

这是由于编译器对其进行了优化,while(!exit)因为内部没有修改exit变量且没有声明为volatile类型,JVM会把判断提前,类似于优化成如下。

if(exit)

{

    while(true)

    {

         doSomeThing();

    }

}

所以main函数虽然对其进行了exit=true的操作,但是由于已经跳过了判断阶段,所以不会起作用了。

注:在没有同步的情况下,编译器、处理器以及运行时等操作的执行顺序进行意想不到的调整。在缺乏足够同步的多线程程序中,要相对内存的执行顺序进行判断,几乎无法得到正确的结论。《java并发编程实践》

在while循环中添加System.out.prinln()时不会有这样的死循环发生,也许对有IO操作的while循环也不会进行优化? --谁知道告诉我下。

 

package Volatile;

public class TestVolatile1 {
	
	public static boolean exit = false;
	public static int count = 0;
	public static void main(String[] args) 
	{
		TestVolatile1 tv = new TestVolatile1();
		testThread thread =	tv.new testThread();
		thread.start();
		
		//消耗时间,避免先设置exit,后执行线程。
		for(int i =0; i < 100; i++)
		{
			System.out.println("waste time!");
		}
		
		exit = true;
		
	}

	private  class testThread extends Thread
	{
		
		public void run()
		{
			
			while(!exit)
			{
				count ++;
//				System.out.println("count" + count);  //添加打印会导致exit=true生效?
			}
			System.out.println("EXIT! count is :" + count);
		}
	}
	
	
}

通过上面的程序可以看出来,volatile的一个作用就是告诉编译器不要给我乱排序,不要优化我,这样保证了对其操作的原子性(赋值,获取等),java不会把获取到一半的时候就进行其他操作,切换线程。但是需要注意的是例如count++与count=count+1,并不是原子的。因为他分为了获取,赋值两个操作。例如count=i+1,就是原子的,因为就赋值一个操作。

另个volatile变量的特点就是不会被缓存在寄存器(线程的内存中)或者其他处理器不可见的地方。保证操作的volatile变量没有复制版本,只有一个内存空间进行存储,因此多线程在访问volatile变量时获取的都是最新的值,但需注意的是如上面所说的他只能保证可见性,不能保证对其操作的原子性,因此在多线程操作的时候可能也会出现数据失效的情况,例如下面程序只有coun1能够正确输出1000;

package Volatile;

public class TestVolatile extends Thread{

	/**
	 * @param args
	 */
	
	static  volatile int count = 0;
	static  volatile int count1 = 0;
	
	static  int count2 = 0;
	
	
	public static synchronized  void inc()
	{
		count1++;
	}
	
	public static  void inc2()
	{
		count2++;
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread []tArray = new Thread[100];
		for(int i =0; i < 100; i++)
		{
			tArray[i] = new TestVolatile();
		}
		
		for(int i = 0; i < 100; i++)
		{
			tArray[i].start();
		}
		
		for(int i = 0; i < 100; i++)
		{
			try {
				tArray[i].join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		System.out.println("count is :" + TestVolatile.count);
		System.out.println("count1 is :" + TestVolatile.count1);
		System.out.println("count2 is :" + TestVolatile.count2);
	}
	
	public void run()
	{
		for(int i = 0; i < 10; i++)
		{
			count ++;
			inc2();
			inc();
			try {
				sleep(3);
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	

}


输出结果:

count is :996
count1 is :1000
count2 is :997


 

 


 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值