• 多线程之volatile关键字(五)


    开始全文之前,先铺垫一下jvm基础知识以及线程栈:

    JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址。

     
     
     
    接下来说说volatile:

    用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。如果要深入了解volatile关键字的作用,就必须先来了解一下JVM在运行时候的内存分配过程。在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图描述这写交互!

     
     
    有了以上知识做铺垫,接下来直接上代码:
    package thread;
    
    public class VolatiDemo1
    {
    	private static volatile boolean flag = true;
    	private static final ThreadLocal <Integer> length = new ThreadLocal <Integer>(){
    		@Override
    		protected Integer initialValue()
    		{
    			return 60;
    		}
    	};
    	
    	public static void main(String[] args)
    	{
    		//模拟兔子
    		new Thread(new Runnable()
    		{
    			int rabbitLength = 0;
    			@Override
    			public void run()
    			{
    				while(flag){
    					try
    					{
    						Thread.sleep(1000);
    						rabbitLength = rabbitLength + 3;
    						System.out.println("兔子跑了 rabbitLength " + rabbitLength + " 米,还剩下:"+
    								(length.get() - rabbitLength) +" 米--------------------");
    						
    						if(rabbitLength == length.get())
    						{
    							System.out.println("兔子获得第一名");
    							flag = false;
    						}
    					} catch (InterruptedException e)
    					{
    						e.printStackTrace();
    					}
    				}
    			}
    		}).start();
    		
    		//模拟乌龟
    		new Thread(new Runnable()
    		{
    			int tortoiseLength = 0;
    			@Override
    			public void run()
    			{
    				while(flag){
    					try
    					{
    						Thread.sleep(1000);
    						tortoiseLength = tortoiseLength + 1;
    						System.out.println("乌龟 跑了 tortoiseLength " + tortoiseLength + " 米,还剩下 "
    								+ (length.get() -tortoiseLength) +"米");
    						
    						if(tortoiseLength == length.get())
    						{
    							System.out.println("乌龟获得第一名");
    							flag = false;
    						}
    					} catch (InterruptedException e)
    					{
    						e.printStackTrace();
    					}
    				}
    			}
    		}).start();
    		
    		try
    		{
    			Thread.sleep(8000);
    			flag = false;
    		} catch (InterruptedException e)
    		{
    			e.printStackTrace();
    		}
    	}	
    }
    	
    

      

     
  • 相关阅读:
    2016.6.21 -Dmaven.multiModuleProjectDirectory system propery is not set,Check $M2_HOME environment variable and mvn script match.
    2016.6.21 maven:Failure to transfer ... from ....
    2016.7.5 如何在maven中添加所需依赖(只知道jar包的部分名字的情况)
    2016.6.20 maven更改repository的位置
    2016.6.20 maven下载与安装步骤
    2016.6.20 在Eclipse配置Tomcat服务器的步骤
    2016.6.21 eclipse配置server locations时按钮为灰色
    2016.6.21 将Eclipse中项目部署到tomcat下
    2016.6.20 tomcat安装出现No Java Virtual Machine found in..
    vue小荔枝,时间控件,动态按月份增减。
  • 原文地址:https://www.cnblogs.com/chen1-kerr/p/6900044.html
Copyright © 2020-2023  润新知