java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解

一、JMM(java memory model)内存模型

从网上淘来二张图:

上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条)。工作时,CPU的高速缓存中的数据通过一系列手段来保证与主内的数据一致(CacheCoherence),更直白点,高速缓存要从主内中load数据,处理完以后,还要save回主存。

 

上图说的是,java中的各种变量(variable)保存在主存中,然后每个线程自己也有自己的工作内存区(working memory),工作时,线程从主存中把变量副本load到自己的工作内存区,处理完了,再save回主存。

好象很明白,没有什么不好理解的:),

问题来了,如果有二个线程:线程A与线程B, A从主存中读取了变量x(到自己的的工作内存区),正准备处理,这时B修改了主存中的变量x,线程A能看见这种变化吗?(是否需要及时从主存中,加载最新的值),这个问题称为共享变量的可见性。

 

二、volatile、synchronized、AtomicXXX

直接上码:

2.1 版本1

package test.cn.mwee.order.monitor;

/**
 * Created by 菩提树下的杨过 on 2017/6/11.
 */
public class ThreadTest extends Thread {

    private static boolean flag = false;

    public void run() {
        System.out.println("t1:" + Thread.currentThread().getId());
        while (!flag) {

        }
        System.out.println("quit!");
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest t1 = new ThreadTest();
        t1.start();
        Thread.sleep(50);
        ThreadTest.flag = true;
        System.out.println("main:" + Thread.currentThread().getId());
    }
}

ThreadTest是一个线程类,里面有一个静态变量flag,然后写了个main方法做测试。

注:在t1启动完成后,主线程中修改了ThreadTest的静态变量值flag,这时t1的run方法里的while循环,其实是看不见主线程对这个值的修改,所以程序始终不能退出,打印不出那一行quit.

 

2.2 版本2

package test.cn.mwee.order.monitor;

/**
 * Created by 菩提树下的杨过 on 2017/6/11.
 */
public class ThreadTest extends Thread {

    private static boolean flag = false;

    public void run() {
        System.out.println("t1:" + Thread.currentThread().getId());
        while (!flag) {
            synchronized (Class.class) {
            }
        }
        System.out.println("quit!");
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest t1 = new ThreadTest();
        t1.start();
        Thread.sleep(50);
        ThreadTest.flag = true;
        System.out.println("main:" + Thread.currentThread().getId());
    }
}  

相对版本1,while循环中增加了一个synchronized同步代码块,虽然里面啥代码也没有,但是再次运行,能正常quit了(想下为啥?)

答案:(也是从网上抄来的)

synchronized关键字强制实现一个互斥锁,使得被保护的代码块在同一时间只能有一个线程进入并执行。

时间: 2024-11-05 22:03:44

java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解的相关文章

Java学习之Java的运行环境

Java 时下已经非常流行.全球每天有超过百万的程序员在用Java进行着程序的开发.用Java编写的程序也因为其硬件环境无关性而越来越受到人们的青睐.如果您希望成为Java世界的一员,那就看看这个系列的文章也许对您会有帮助. 无论哪种语言都需要有它特定的运行环境也就是平台,Java 同样不例外.您也许会问,Java程序不是有硬件环境无关性吗?好吧,我希望这篇文章可以回答好这个问题. 几乎所有的语言都是需要通过编译或者解释才可以被您的电脑执行.可是Java有一点不同,它同时需要这两个过程.其实,也

Java学习之——Java Serializable

1.什么是Serializable接口? http://en.wikipedia.org/wiki/Serialization Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据.有关对象的类型的信息和存储在对象中数据的类型. 将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息.对象的数据,还有对象中的数据类型可以用来在内存中新建对象. 整个过程都是Java虚拟机(JVM)独立的,也就是说,在一

Java学习之Java的单例模式

单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中.每台计算机可以有若干通信端口,系统应当集中管理这

同步和Java内存模型(五)Volatile

原文链接: http://gee.cs.oswego.edu/dl/cpj/jmm.html 作者:Doug lea 译者:杜建雄  校对者:方腾飞 Volatile 从原子性,可见性和有序性的角度分析,声明为volatile字段的作用相当于一个类通过get/set同步方法保护普通字段,如下: 查看源代码 打印帮助 1 final class VFloat { 2     private float value; 3   4     final synchronized void set(flo

Java学习之踏上旅途的第一步

在上一篇文章<Java学习之Java的运行环境> 中,我们了解了Java运行平台的基本概念,在这篇文章中,让我们来看看如何自己动手安装和配置Java平台,并开始一步步的编写我们的第一个Java小程序. Java开发平台的种类很多,在这篇文章中我主要以J2SE为例子.J2SE几乎是开发所有Java应用程序的必备.它主要是由一个compiler(编译器),一个运行环境(runtime environment),和一个核心的API所构成.我们要再次要强调的是,您所编写应用程序并不是直接在您的本地操作

Java Memory Model

[原文地址] The Java memory model specifies how the Java virtual machine works with the computer's memory (RAM). The Java virtual machine is a model of a whole computer so this model naturally includes a memory model - AKA the Java memory model. It is ver

深入理解Java内存模型(四)——volatile

volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步.下面我们通过具体的示例来说明,请看下面的示例代码: class VolatileFeaturesExample { //使用volatile声明64位的long型变量 volatile long vl = 0L; public void set(long l) { vl = l;

Java学习笔记

笔记 本笔记是在看浙大翁恺老师的视频教学时所做,希望对Java初学者有帮助! 一.Java基础1.正确认识Java(1)Java是一种有生产力的OOP语言,C++能做的Java都能做(2)Java与网络关系不大,更不是用来做网页的(3)Java是UNIX世界的产物,具有UNIX的思想(4)Java在国外广泛的被用来做各种应用2.Java历史(1)Brithday:May 23,1995(2)1991:Set-Top box:Jame Gosling(3)1994:OAK and FirstPer

【Java学习路线图,看你掌握了多少】附全部知识点免费视频课程,名师主讲

这个路线图中包含了Java学习的三部曲: Java零基础入门(点击标题学习) Java面向对象开发(点击标题学习) Java高级开发(点击标题学习) 在阿里云大学,你可以跟随Java名师李兴华学到路线图中所有的知识点(完全免费哦),赶快开始你的Java学习之路吧! 课程详细目录: Java零基础入门 课时1:Java简介(Java发展概述) 课时2:Java简介(Java主要特点) 课时3:JDK的安装与配置 课时4:第一个Java程序 课时5:CLASSPATH环境属性 课时6:Java程序基