`
zwt2001267
  • 浏览: 435337 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java中关键字volatile的作用

    博客分类:
  • Java
阅读更多

 

什么是原子操作? 

所谓原子操作,就是"不可中断的一个或一系列操作" , 在确认一个操作是原子的情况下,多线程环境里面,我们可以避免仅仅为保护这个操作在外围加上性能昂贵的锁,甚至借助于原子操作,我们可以实现互斥锁。 很多操作系统都为int类型提供了+-赋值的原子操作版本,比如 NT 提供了 InterlockedExchange 等API, Linux/UNIX也提供了atomic_set 等函数。 

 

关于java中的原子性? 

原子性可以应用于除long和double之外的所有基本类型之上的“简单操作”。对于读取和写入出long double之外的基本类型变量这样的操作,可以保证它们会被当作不可分(原子)的操作来操作。 因为JVM的版本和其它的问题,其它的很多操作就不好说了,比如说++操作在C++中是原子操作,但在Java中就不好说了。 另外,Java提供了AtomicInteger等原子类。再就是用原子性来控制并发比较麻烦,也容易出问题。 

 

volatile原理是什么? 

Java中volatile关键字原义是“不稳定、变化”的意思 

使用volatile和不使用volatile的区别在于JVM内存主存和线程工作内存的同步之上。volatile保证变量在线程工作内存和主存之间一致。 

其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我. 

 

以下一段有意思的代码:

package jdk.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestMultiThread implements Runnable {

	private static int i;

	private static volatile Integer vi = 0;

	private static AtomicInteger ai = new AtomicInteger();

	private static Integer si = 0;
	
	private static int ri;

	private static AtomicInteger flag = new AtomicInteger();

	private Lock lock = new ReentrantLock();

	@Override
	public void run() {
		for (int k = 0; k < 200000; k++) {
			i++;
			vi++;
			ai.incrementAndGet();
			synchronized (si) {
				si++;
			}
			lock.lock();
			try {
				ri++;
			} finally {
				lock.unlock();
			}

		}
		flag.incrementAndGet();
	}
	
	public static void main(String[] args) throws InterruptedException {
		TestMultiThread t1 = new TestMultiThread();
		TestMultiThread t2 = new TestMultiThread();
		ExecutorService exec1 = Executors.newCachedThreadPool();
		ExecutorService exec2 = Executors.newCachedThreadPool();
		exec1.execute(t1);
		exec2.execute(t2);
		while (true) {
			if (flag.intValue() == 2) {
				System.out.println("i           		>>>>>" + i);
				System.out.println("volatile vi 		>>>>>" + vi);
				System.out.println("AtomicInteger ai	>>>>>" + ai);
				System.out.println("synchronized si		>>>>>" + si);
				System.out.println("lock ri			>>>>>" + ri);
				exec1.shutdown();
				exec2.shutdown();
				break;
			}
			Thread.sleep(50);
		}
	}

}

 运行结果如下:

i           >>>>>395805

volatile vi >>>>>369741

AtomicInteger ai>>>>>400000

synchronized si>>>>>379400

lock ri>>>>>392087

 

volatile因为java中++不是原子操作,所以值不正确。

synchronized 锁定的不是同一个对象,因为si对象一直在变,改成如下代码则正确:

synchronized (Integer.class) {
				si++;
			}

 

lock 锁定的不是同一个对象,加static关键字修饰,改成类变量则正确。

private static Lock lock = new ReentrantLock();

 

参考:http://blog.csdn.net/luohuacanyue/article/details/7796352

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics