java-多线程深入(一)JMM

(一)java内存区域概况

jvm运行java程序时把所管理的内存分成几个部分:方法区、java栈、本地方法栈、java堆、pc程序计数器。

class字节码装载解析后,在多线程环境中,方法区和java堆数据共享,每个线程自带pc程序计数器和java栈,栈帧中包含方法的所有状态(局部变量、传参、返回值、运算中间结果等)。对共享数据需要考虑多线程并发问题。

更详细内容可参考《深入理解JVM虚拟机》

(二)计算机系统原型

1.内存和处理器速度不同,缓存的出现,导致数据不同步

多线程都有缓存备份,回写可能会导致数据错误

2.处理器和编译器对代码和指令的优化,导致运算乱序

只要不影响运算结果,处理器可以调整代码执行顺序,多线程操作中会导致数据错误

(三)JMM概况

JMM(java momery model)提供了线程进行通讯时,确保互斥性和可见性。

(1)解决内存可见性问题

共享数据放主内存中,每个线程有自己的工作内存。

线程A读取数据时,先从主内存拷贝数据到工作内存,进行运算后再从工作内存回写到主内存,线程间无法相互访问对方的数据,通过主内存实现通讯。

JMM可以控制指定共享数据实现内存可见性,写入主内存时,同步更新其他线程中的变量值,如volatile变量的使用。

(2)禁止重排序

编译器优化代码,不改变运算结果的情况下,可以实现代码重排序;处理器执行指令,不改变运算结果的情况下,可以实现指令重排序。

JMM可以禁止编译器代码重排序和处理器执行指令重排序(通过加入内层屏蔽)。

多线程并发问题代码剖析

/**
 * 代码重排序demo
 *
 * @author peter_wang
 * @create-time 2015-1-8 下午3:06:02
 */
public class CodeChangeDemo {

    private static boolean isChange = false;

    private static class ChangeThread
        extends Thread {
        public void run() {
            System.out.println("ChangeThread start"); //1
            isChange = true;                          //2
        };
    };

    private static class GetChangeThread
        extends Thread {
        public void run() {
            System.out.println("GetChangeThread start");
            if (isChange) {                           //3
                isChange = false;
                System.out.println("change success");
            }
            else {
                System.out.println("change no success");
                System.exit(0);
            }
        };
    };

    /**
     * @param args
     */
    public static void main(String[] args) {
        while (true) {
            ChangeThread changeThread = new ChangeThread();
            GetChangeThread getChangeThread = new GetChangeThread();
            changeThread.start();
            getChangeThread.start();
            // 防止线程过多,等执行完上面俩线程再继续
            while (Thread.activeCount() > 1) {

            }
        }
    }

}

运行结果:

ChangeThread start

GetChangeThread start

change success

ChangeThread start

GetChangeThread start

change success

ChangeThread start

GetChangeThread start

change no success

进程退出可能原因:

1.线程ChangeThread中代码顺序调整,1和2调换,执行顺序1-3-2

2.线程ChangeThread执行完,工作内存中的isChange没有回写回主内存,导致3中isChange不是最新值。

参考文献:

1.《深入理解JVM虚拟机》

2.http://ifeve.com/java-memory-model-1/

时间: 2024-10-01 03:54:51

java-多线程深入(一)JMM的相关文章

Java多线程 -- 单例模式的Double-checked Locking (DCL)问题

Double-checked Locking (DCL)用来在lazy initialisation 的单例模式中避免同步开销的一个方法. 下面是这么做的一个例子. [java] view plaincopy public class MyFactory { private static MyFactory instance; public synchronized static MyFactory getFactory() { if (instance == null) instance = 

Java多线程的三大特性,线程池,JMM(Java内存模型)

一,线程的三大特性:原子性.可见性.有序性 1)原子性,即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行.原子性其实就是保证数据一致.线程安全一部分. 2)可见性,即当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值. 3)有序性,即程序执行的顺序按照代码的先后顺序执行.二.JAVA多线程的内存模型 共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入时,能对另一个线程可见.从抽象的角度来看,

Java多线程编程模式实战指南(二):Immutable Object模式--转载

本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-object.转载请注明作者: 黄文海 出处:http://viscent.iteye.com. 多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线程安

Java多线程感悟二

写在前面 这篇是Java多线程感悟的第二篇博客,主要讲述的JAVA层面对并发的一些支持.第一篇博客地址为:http://zhangfengzhe.blog.51cto.com/8855103/1607712  下一篇博客将介绍线程池和一些同步工具类. 目录 9.  并发内存模型及并发问题概述 10. volatile和synchronized原理分析 11. ThreadLocal原理及其在Struts/Spring中的应用 12. Atomic 13. Lock 并发内存模型及并发问题概述 首

Java多线程具体解释

Java多线程具体解释 多线程简单介绍 概述 多线程(multithreading).是指从软件或者硬件上实现多个线程并发运行的技术.具有多线程能力的计算机因有硬件支持而可以在同一时间运行多于一个线程,进而提升总体处理性能.具有这样的能力的系统包含对称多处理机.多核心处理器以及芯片级多处理或同一时候多线程处理器.在一个程序中,这些独立运行的程序片段叫作"线程"(Thread),利用它编程的概念就叫作"多线程处理". 具有多线程能力的计算机因有硬件支持而可以在同一时间

java多线程与内存可见性

一.java多线程 JAVA多线程实现的三种方式: http://blog.csdn.net/aboy123/article/details/38307539 二.内存可见性 1.什么是JAVA 内存模型 共享变量 :如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量. Java Memory Model (JAVA 内存模型)描述线程之间如何通过内存(memory)来进行交互,描述了java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存

[转] Java多线程发展简史

这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并且提及一些在多线程编程方面常见的问 题.对于Java程序员来说,如果从历史的角度去了解一门语言一个特性的演进,或许能有不同收获. 引言 首先问这样一个问题,如果提到Java多线程编程,你会想到什么? ● volatile.synchronized关键字? ● 竞争和同步? ● 锁机制? ● 线程安全

Java多线程和并发总结

Java多线程和高并发总结 wait/notify必须存在于synchronized块中. volatile多线程的内存模型:main memory(主存).working memory(线程栈),在处理数据时,线程会把值从主存load到本地栈,完成操作后再save回去(volatile关键词的作用:每次针对该变量的操作都激发一次load and save) Thread类最佳实践: 写的时候最好要设置线程名称 Thread.name,并设置线程组 ThreadGroup,目的是方便管理.在出现

***Java多线程发展简史

http://blog.jobbole.com/28297/ 本文来自四火的博客(@RayChase),由@_Zhijun 推荐 这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并且提及一些在多线程编程方面常见的问题.对于Java程序员来说,如果从历史的角度去了解一门语言一个特性的演进,或许能有不同收获. 引言 首先问这样一个问题,如果提到Java

JAVA多线程编程——JAVA内存模型

一.何为"内存模型" 内存模型描述了程序中各个变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节,对象最终是存储在内存里面的,但是编译器.运行库.处理器或者系统缓存可以有特权在变量指定内存位置存储或者取出变量的值. 二.JMM(Java Memory Model)即Java内存模型的作用 JMM的最初目的是为了能够支持多线程程序.JMM使得每一个线程就像运行在不同的机器.不同的CPU或者本身就不同的线程上一样: JMM定义