zoukankan      html  css  js  c++  java
  • voliatle关键字

    1.volatile关键字使用:

      多线程中存在私有堆栈中的值和公共堆栈中的值不同步的问题。什么意思呢?可能线程在一个地方修改了内存中变量的值,而其它地方线程却从私有堆栈中去读取不一致的变量值。关键字volatile 的主要作用是使在多个线程上可见。也就是,强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。

    • 线程的私有堆栈:

    • 读取公共内存:

    强制从私有堆栈中取值的方法为JVM被设置为-server(不设置-server也是从私有堆栈中获取值)。

    package chapter2;
    
    public class VolatileTest {
    	
    	
    	static class RunThread extends Thread{
    	        private boolean isRunning = true;
    
    		public boolean isRunning() {
    			return isRunning;
    		}
    
    		public void setRunning(boolean isRunning) {
    			this.isRunning = isRunning;
    		}
    		
    		@Override
    		public void run() {
    			super.run();
    			System.out.println("进入run 了");
    			while (isRunning) {
    				
    			}
    			System.out.println("线程被停止了!");
    		}
    	}
    	
    	public static void main(String[] args) {
    		try {
    			RunThread runThread = new RunThread();
    			runThread.start();
    			Thread.sleep(1000);
    			runThread.setRunning(false);
    			System.out.println("已经赋值为false");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    	}
    
    }
    

    运行结果:

    进入run 了
    已经赋值为false
    永远不会打印线程被停止了!

    volatile private boolean isRunning = true;//强制从公共堆栈中取得变量的值

    运行结果:

    进入run 了
    已经赋值为false
    线程被停止了!

    非原子性验证:

    package chapter2;
    
    public class VolatileThread extends Thread{
    	volatile public static int count;
    	private static void addCount() {
    		for(int i=0;i<100;i++) {
    			count++;
    		}
    		System.out.println("Thread:"+currentThread().getName()+"--count:"+count);
    	}
    	
    	@Override
    	public void run() {
    		super.run();
    		addCount();
    	}
    
    }
    
    package chapter2;
    
    public class VolatileTest {
    	
    	public static void main(String[] args) {
    		VolatileThread[] volatileThreads = new VolatileThread[100];
    		for (int i = 0; i < 100; i++) {
    			volatileThreads[i] = new VolatileThread();
    		}
    		
    		for(int i=0;i<100;i++) {
    			volatileThreads[i].start();
    		}
    	}
    
    }
    

     运行结果:

    Thread:Thread-84--count:8683
    Thread:Thread-88--count:8863
    Thread:Thread-89--count:8863
    Thread:Thread-87--count:8963
    Thread:Thread-90--count:9063
    Thread:Thread-92--count:9163
    Thread:Thread-97--count:9663
    Thread:Thread-96--count:9563
    Thread:Thread-98--count:9763
    Thread:Thread-95--count:9863
    Thread:Thread-93--count:9463
    Thread:Thread-94--count:9363
    Thread:Thread-91--count:9263
    Thread:Thread-99--count:9963

    非原子性的原因:

    • read 和 load 阶段:从主存复制变量到当前线程工作内存。
    • use 和 assign 阶段:执行代码,改变共享变量值。
    • store 和 write 阶段:用工作内存数据刷新主存对应变量的值。

       在多线程环境中,use和assign 是多次出现的,但这一操作并不是原子性,也就是说在read和load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,也就是私有内存和公有内存的变量不同步,所以计算出来的结果和预期不一样,也就出现了非线程安全的问题。

    2.使用原子类进行i++操作

    package chapter2;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class VolatileThread extends Thread{
    	private AtomicInteger count = new AtomicInteger(0);
    	private void addCount() {
    		for(int i=0;i<10000;i++) {
    			System.out.println(count.incrementAndGet());
    		}
    	}
    	
    	@Override
    	public void run() {
    		super.run();
    		addCount();
    	}
    
    }
    
    package chapter2;
    
    public class VolatileTest {
    	
    	public static void main(String[] args) {
    		try {
    			VolatileThread volatileThread = new VolatileThread();
    			Thread t1 = new Thread(volatileThread);
    			t1.start();
    			Thread t2 = new Thread(volatileThread);
    			t2.start();
    			Thread t3 = new Thread(volatileThread);
    			t3.start();
    			Thread t4 = new Thread(volatileThread);
    			t4.start();
    			Thread t5 = new Thread(volatileThread);
    			t5.start();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    	}
    
    }
    

    运行结果:

    49990
    49991
    49992
    49993
    49994
    49995
    49996
    49997
    49998
    49999
    50000

    成功累加到50000!

  • 相关阅读:
    winform 调用http 通过代理出现的一系列问题
    【转】 CSS3阴影 box-shadow的使用和技巧总结
    【转】 C#程序以管理员权限运行
    【转】WMI使用的WIN32_类库名
    【转】C#取硬盘、CPU、主板、网卡的序号 ManagementObjectSearcher
    【转】纯CSS设置Checkbox复选框控件的样式
    【转】vs2012 打包安装更改 setup.exe的图标
    【转】VS2012程序打包部署详解
    142. Linked List Cycle II
    141. Linked List Cycle
  • 原文地址:https://www.cnblogs.com/hunter-56213/p/11052185.html
Copyright © 2011-2022 走看看