我们先来看一段代码:

①.线程类,用全局布尔值控制线程是否结束,每隔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。
下一章我们来看一下和原子性有关的操作。
 
用一张图来描述变量在内存中的工作流程:
 
 

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

  1. 多线程(三) java中线程的简单使用

    java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...

  2. Java多线程6:synchronized锁定类方法、volatile关键字及其他

    同步静态方法 synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁.看一下例子,注意一下printC()并不是一个静态方法: public ...

  3. java中 static,final,transient,volatile关键字的作用

    static 和final static  静态修饰关键字,可以修饰 变量,程序块,类的方法: 当你定义一个static的变量的时候jvm会将将其分配在内存堆上,所有程序对它的引用都会指向这一个地址而 ...

  4. 多线程(三) iOS中的锁

    锁的类别:互斥锁,递归锁,条件锁,自旋锁等 锁的实现方式:NSLock,NSRecursiveLock, NSConditionLock,@synchronized,GCD的信号量等 下面说一下常用的 ...

  5. Java多线程(三) 多线程间的基本通信

    多条线程在操作同一份数据的时候,一般需要程序去控制好变量.在多条线程同时运行的前提下控制变量,涉及到线程通信及变量保护等. 本博文主要总结:①线程是如何通信  ②如何保护线程变量 1.Java里的线程 ...

  6. Java 并发和多线程(三) 多线程的代价 [转]

    原文链接:http://tutorials.jenkov.com/java-concurrency/costs.html 作者:Jakob Jenkov     翻译:古圣昌        校对:欧振 ...

  7. 多线程(三)多线程同步_基本介绍及mutex互斥体

    同步进制的引入为了解决以下三个主要问题:1.控制多个线程之间对共享资源访问,保证共享资源的完整性例如:线程A对共享资源进行写入,线程B读取共享资源2.确保多个线程之间的动作以指定的次序发生例如:线程B ...

  8. java多线程(三):多线程单例模式,双重检查,volatile关键字

    一.事先准备 首先准备一个运行用的代码: public class Singleton { public static void main(String[] args) { Thread[] thre ...

  9. 从零开始了解多线程知识之开始篇目 -- jvm&volatile

    CPU多核缓存存储结构图 电脑存储结构概念 多CPU 一个现代计算机通常由两个或者多个CPU,如果要运行多个程序(进程)的话,假如只有 一个CPU的话,就意味着要经常进行进程上下文切换 因为单CPU即 ...

随机推荐

  1. python学习之路---day06

    一:is 和 == 的区别 01)a b 两个变量 is 是比较变量的内存地址,如果地址相等,则返回True,如果不相等,则返回False == 是比较变量两边内容是否一样,如果一样则返回True,不 ...

  2. Little Elephant and Magic Square

    Little Elephant loves magic squares very much. A magic square is a 3 × 3 table, each cell contains s ...

  3. HDU_6298 Maximum Multiple 【找规律】

    一.题目 Given an integer $n$, Chiaki would like to find three positive integers $x$, $y$ and $z$ such t ...

  4. 【AC自动机】【字符串】【字典树】AC自动机 学习笔记

    blog:www.wjyyy.top     AC自动机是一种毒瘤的方便的多模式串匹配算法.基于字典树,用到了类似KMP的思维.     AC自动机与KMP不同的是,AC自动机可以同时匹配多个模式串, ...

  5. DictionaryHelper

    /// <summary> /// DictionaryHelper /// </summary> public static class DictionaryHelper { ...

  6. jstl 遍历数据

    1   导入 jstl  的  jar 包 2. 页面中添加 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/ ...

  7. 在Eclipse中添加Servlet-api.jar的方法

    方法一: 正确的加载servlet-api.jar的方法如下: 1:右击项目工程名称 2:Properties 3:  Jvav Build Path 4:  Libraries 5:  Add Ex ...

  8. hdu2588 GCD

    GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  9. android apk重新[签名]

    1,删除之前的签名文件 用解压缩工具打开,删除 [META-INF] 文件夹 2,打开命令行窗口 3,[保证签名文件和apk在同一级目录下] 然后执行如下命令,将 (xx) 处替换自己的签名.apk ...

  10. ibatis配置文件中的XML解析错误The content of elements must consist of well-formed character data or markup.

    在检查过所有的标签名都没有问题的情况下. xml中的小于号属于非法字符. SQL语句中则可能需要小于号,此时就需要用<![CDATA[  ]]>将小于号包裹,如此不会被xml解析器解析. ...