System.out.println当输出一个属性的时候是会读相关属性的真实内存地址上的数据同时做一次同步

来源:互联网 发布:智慧树网络课答案2017 编辑:程序博客网 时间:2024/06/05 00:37


package com.yikuyi.volatileTest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RunThread  extends Thread{

 private static final Logger logger = LoggerFactory.getLogger(RunThread.class);
 
 private boolean running = true;
 
 private int a = 0;
 
 private void setRunning(boolean running){
  System.out.println("&&&&&&&&&&&&&&&&----setRunning-----"+Thread.currentThread().getName());
  this.running = running;
 }
 
 @Override
 public void run(){
  System.out.println("进入run方法......");
  System.out.println("----run-------"+Thread.currentThread().getName()+"--------running:"+running);
  while(running){
//   System.out.println("--------while--------"+Thread.currentThread().getName()+"----------"+running);
   a++;
  }
  System.out.println("线程停止"+"--------------------"+Thread.currentThread().getName());
 }
 
 
 public static void main(String[] args) throws InterruptedException {
  RunThread runThread = new RunThread();
  runThread.start();
  Thread.sleep(3000);
  runThread.setRunning(false);
  System.out.println("--------running-----set-----false-----");
  Thread.sleep(1000);
  System.out.println(Thread.currentThread().getName()+"************"+runThread.running+"**********");
 }
 
}



楼主,你这个问题其实很常见,这个是由java虚拟机的机制导致的,虚拟机为了效率,在处理线程类的属性时会创建一个临时属性,比如你一个线程类有一个子属性int a,在线程高速运行的时候,线程外部对这个a的修改并不能及时传达至内部,因为是非原子操作,同样线程内部对这个a 的修改也不能及时传达至外部,因为在线程外部调用这个属性a和线程内部调用这个属性a其实不是一个内存地址,只是看起来是同一个变量罢了,这个类似一种线程内部的缓存机制,可以确定的是当这个线程运行结束时,这个属性的值才会统一,至于在线程运行期间这个属性的值是不是能同步是不确定的,解决的办法可以采用sleep,你那个System.out.println也算是一种解决办法,我理解的当输出一个属性的时候是会读相关属性的真实内存地址上的数据同时做一次同步,除了这两个看起来不雅的办法,还可以用原子操作来解决可以参考下 AtomicInteger  这个类的api,这个类是一个原子操作的类,可以确保你多线程运行过程中内部和外部数据的统一,但是也略微降低了程序效率



查看地址:http://bbs.csdn.net/topics/391077210?page=1

阅读全文
0 0