zoukankan      html  css  js  c++  java
  • 多线程之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();
    		}
    	}	
    }
    	
    

      

     
  • 相关阅读:
    git 备查
    PyQt5 信号与槽机制
    Python 循环报错 'int' object is not iterable
    docker instructions命令及dockerfile实践
    shell脚本中set指令
    你知道什么是Python算法和数据结构、抽象数据和面向对象、数组和列表、链表吗?
    Python爬虫抓取B站人类高质量男性求偶视频的弹幕,康康都在讨论什么!❤️
    Python从入门到精通要掌握哪些基础知识?
    想搞个恶作剧吗? 代码丢给他,生死有命富贵在天,看我学会python用代码整蛊朋友
    妹妹画的小恐龙和我用Python画的小恐龙,你更加喜欢谁的!❤️
  • 原文地址:https://www.cnblogs.com/chen1-kerr/p/6900044.html
Copyright © 2011-2022 走看看