多线程(三)~多线程中数据的可见性-volatile关键字

我们先来看一段代码:
①.线程类,用全局布尔值控制线程是否结束,每隔1s打印一次当前线程的信息
  1. package com.multiThread.thread;
  2. publicclassPrintStringimplementsRunnable{
  3. privateboolean isContinuePrint =true;
  4. @Override
  5. publicvoid run(){
  6. while(isContinuePrint){
  7. try{
  8. System.out.println("current threadId is "+Thread.currentThread().getId()+",threadName is"+Thread.currentThread().getName()+",threadPriority "+Thread.currentThread().getPriority());
  9. Thread.sleep(1000);
  10. }catch(InterruptedException e){
  11. e.printStackTrace();
  12. }
  13. }
  14. System.out.println("Thread is stop!");
  15. }
  16. publicboolean isContinuePrint(){
  17. return isContinuePrint;
  18. }
  19. publicvoid setContinuePrint(boolean isContinuePrint){
  20. this.isContinuePrint = isContinuePrint;
  21. }
  22. }
②.测试类
  1. package com.multiThread.test.common;
  2. import com.multiThread.thread.PrintString;
  3. publicclassVolatileTest{
  4. publicstaticvoid main(String[] args){
  5. PrintString printString =newPrintString();
  6. Thread t =newThread(printString);
  7. t.start();
  8. try{
  9. Thread.sleep(2000);
  10. printString.setContinuePrint(false);
  11. }catch(InterruptedException e){
  12. e.printStackTrace();
  13. }
  14. }
  15. }
打印结果:
  1. current threadId is 8,threadName isThread-0,threadPriority 5
  2. current threadId is 8,threadName isThread-0,threadPriority 5
  3. Thread is stop
 
以上这段程序在我本地的eclipse上运行完全没有问题,但是一段以服务器端的参数来运行则会出现问题。
我们修改一下eclipse的运行方式,带上参数-server来运行这段代码,擦,运行结果还是这样,又没成功,我命名是win7+jdk64位啊。
先不管了,按照书上说的,这块停不下来。那为什么停不下来呢?因为服务器为了兼顾性能直接从当前线程的工作内存中获取的值,没有从主内存中取。而main函数里的操作是把主内存的数据给更新了,听起来类似于程序的读缓存没查库的操作。
 
解决的方式就是为变量此变量加上volatile关键字来修饰。volatile关键字修饰的变量会强制从主内存中读取数据,保证数据的可见性。
此关键字的应用场景为:多线程中可以感知实例变量被更改了。并且可以获得最新的值使用,也就是多线程读取共享变量时可以获得最新的值使用
  1. privatevolatileboolean isContinuePrint =true;
 
附带volatile关键字的工作图:
 
当然,此处也可以采用synchronize的方式来处理,不过synchronize和volatile关键字的作用是不同的。
这里要注重强调一下二者的区别和作用:
volatile:强制从主内存读取数据,保证数据的可见性。volatile的操作不是原子性的。
synchronize:同步操作,保证一次监视对象一次只有一个线程去处理。synchronize本身也可以保证数据的可见性,同时更重要的是用来保证数据的同步性。
 
多线程这块的处理都是围绕着数据的同步性、可见性和原子性来操作的,记住这个原则就OK。
下一章我们来看一下和原子性有关的操作。
 
用一张图来描述变量在内存中的工作流程:
 
 





posted @ 2017-02-27 14:12  鱼我所欲也  阅读(708)  评论(0编辑  收藏  举报