volatile 解析

版权声明:如需转载,请标明转载出处哦! https://blog.csdn.net/Z0157/article/details/81489930

volatile: 使变量在多个线程间可见
    
    (1)、在java中每一个线程都会有一块工作内存,其中存放着是所有线程共享的主内存的变量值的拷贝。
    (2)、当前线程执行时,他在自己的工作内存区操作这些变量。
    (3)、为了存取一个共享的变量,一个线程通常是先获取锁定并清除他的内存工作区,把共享变量从
            所有的线程的共享内存中正确装入到他自己的工作内存区域中。
    (4)、当线程解锁的时候保证该工作区的变量的值写回到共享内存中。

作用:volatile的作用是强制线程到主内存(共享内存)里去读取变量,而不是去工作内存区里去读取,
从而实现了多个线程间的变量可见,也是满足线程安全的可见性。


1、volatile关键字虽然拥有读个线程之间的可见性,但是却不具备同步性(也就是原子性);
2、volatile相当于一个轻量级的synchronized,性能比synchronized 强很多,不会造成阻塞,
    像netty中大量使用volatile,但是他并不能待敌synchronized的同步功能,只是针对多个
    线程可见的变量操作。
3、原子性操作可以使用atomic类的系列对象(只能保证本身方法原子性,并不能保证多次操作的原子性)
eg: num.addAndGet(1);
    num.addAndGet(1); 
    连续操作了多次,是无法保证原子性的;

测试代码:

import java.util.concurrent.atomic.AtomicInteger;

/**
 * volatile关键字不具备synchronized关键字的原子性(同步)
 *
 */
public class VolatileNoAtomic extends Thread{
	//private static volatile int count;
	private static AtomicInteger count = new AtomicInteger(0);
	private static void addCount(){
		for (int i = 0; i < 1000; i++) {
			//count++ ;
			count.incrementAndGet();
		}
		System.out.println(count);
	}
	
	public void run(){
		addCount();
	}
	
	public static void main(String[] args) {
		
		VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
		for (int i = 0; i < 10; i++) {
			arr[i] = new VolatileNoAtomic();
		}
		
		for (int i = 0; i < 10; i++) {
			arr[i].start();
		}
	}
	
	
	
	
}
public class RunThread extends Thread{

	private volatile boolean isRunning = true;
	private void setRunning(boolean isRunning){
		this.isRunning = isRunning;
	}
	
	public void run(){
		System.out.println("进入run方法..");
		int i = 0;
		while(isRunning == true){
			//..
		}
		System.out.println("线程停止");
	}
	
	public static void main(String[] args) throws InterruptedException {
		RunThread rt = new RunThread();
		rt.start();
		Thread.sleep(1000);
		rt.setRunning(false);
		System.out.println("isRunning的值已经被设置了false");
	}
	
	
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicUse {

	private static AtomicInteger count = new AtomicInteger(0);
	
	//多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
	/**synchronized*/
	public synchronized int multiAdd(){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			count.addAndGet(1);
			count.addAndGet(2);
			count.addAndGet(3);
			count.addAndGet(4); //+10
			return count.get();
	}
	
	
	public static void main(String[] args) {
		
		final AtomicUse au = new AtomicUse();

		List<Thread> ts = new ArrayList<Thread>();
		for (int i = 0; i < 100; i++) {
			ts.add(new Thread(new Runnable() {
				@Override
				public void run() {
					System.out.println(au.multiAdd());
				}
			}));
		}

		for(Thread t : ts){
			t.start();
		}


	
		

		
	}
}

测试结果我就不贴出来,希望阅读的人自己动手去写,写完了,运行了,对volatile使用也就彻底了解了;

猜你喜欢

转载自blog.csdn.net/Z0157/article/details/81489930