多线程概念的引入体现了人类重新有效压力寨计算机。这是非常有必要的,由于所涉及的读数据的过程中的一般操作,如从磁盘、其他系统、数据库等,CPU计算速度和数据读取速度已经严重失衡。假设印刷过程中一个线程将有非常多节点堵塞,使计算效率低下。

另外,server端是java最擅长的领域,作为server必需要能同一时候响应多个client的请求,相同需要多线程的支持。在多线程情况下。高并发将带来数据的共享与竞争问题。tomcat作为中间件将多线程并发等细节尽量封装起来处理,使用户对多线程透明,很多其它地关注业务处理就可以。但假设想要深入剖析tomcat我们有必要深入了解多线程并发技术。此章节将介绍多线程并发的一些底层原理及JDK并发包的实现的相关知识。并不会对全部具体的并发类的用法进行介绍,针对一些在Tomcat中使用的类会略微具体阐述。

1、Java内存模型——JMM

在多核时代,怎样提高CPU的性能成为了一个永恒的话题,而这个话题的讨论主要就是怎样定义一个高性能的内存模型,内存模型用于定义处理器的各层缓存与共享内存的同步机制及线程和内存交互的规则。

Java的世界也有属于它自己的内存模型,Java内存模型,即Java Memory Model,简称JMM。因为Java被定义成一种跨平台的语言,所以在内存的描写叙述上面也要能是跨平台的。Java虚拟机试图定义一种统一的内存模型,能将各种底层硬件及操作系统的内存訪问差异进行封装,使Java程序在不同硬件及操作系统上都能达到同样的并发效果。它描写叙述了程序中各个变量之间的关系,包含实例域、静态域、数据元素及在实际计算机系统中将变量存储到内存和从内存中取出变量的底层细节。

为更好理解JMM的工作机制。由图2-5-1-1带入。从总体上看有几个比較重要的主体。主存、工作内存、变量、变量副本、线程等。首先看主存与工作内存及他们的关系,主存保存了java程序的全部变量,当然这个变量不包括局部变量和方法參数,而工作内存则包括了这些变量的副本;其次是线程与工作内存的关系,每一个线程都有一个属于自己的工作内存,不同线程之间的工作内存是互相不可见的,且线程对变量的操作也仅仅能是针对自己的工作内存;最后是关于线程之间的通信机制,因为线程直接不可直接传递,假如一条线程对一个变量进行又一次赋值,那么仅仅能通过例如以下途径让另外一条线程知道,线程一将变量改变反应到主存中,线程二再从主存中读取,这样就基本完毕了线程之间的通信了。

JMM定义额八个操作来完毕工作内存与主存的通信。假如一条线程准备对一个变量进行新的赋值操作,它可能会先用lock操作锁住主存中的某个变量(不让其它线程获得此变量的锁。直至使用unlock操作释放该变量的锁),接着使用read操作将变量从主存独到工作内存。紧接着load操作将得到的变量值放到工作内存中的变量副本,use操作则将变量值传给线程运行引擎进行运算操作,assign操作把新的变量值从线程运行引擎中传递到工作内存,继续往下,store操作则把变量值从工作内存传送到主存中,接着write操作将得到的值写入主存对应的变量中。最后使用unlock操作释放变量的锁。

图2-5-1-1 java内存模型JMM

Java内存模型具有三个特性:原子性、可见性和有序性。

①  原子性,java内存模型保证了read、load、assign、use、store、write六个操作具有原子性。我们能够觉得除了long和double类型外。对其它基本数据类型所相应的内存单元的訪问读写都是原子的。

但因为这个原子性的颗粒度太小。通常情况下我们须要更大颗粒度的原子性,这时就须要用锁来保证了。

②  可见性,在java内存模型中,简单说假设一条线程更改了共享变量的值,而其它线程能立即知道这个更改。我们则说这个变量具有可见性。一般来说有四种方式能保证变量的可见性,分别为volatile、synchronized、final和锁。首先谈谈volatile,被此关键词声明的变量。每当有不论什么更改时都将立即同步到主存中,而每一个线程要使用这个变量时都要又一次从主存刷新到工作内存。这样就确保了变量的可见性(当然,普通变量终于也会同步到主存,再由主存同步到每一个线程的工作内存,仅仅是这个终于可能比較“长久”,不能保证可见性)。因为synchronized底层也是通过锁进行实现,所以synchronized和锁的本质是一样的,当一个线程释放一个锁时,将会强制刷新工作内存中的变量值到主存中,而当还有一个线程获取此锁的时候将会强制又一次装载此变量值。当然这两个线程获取的是同一个锁。这样就保证了变量的可见性。被final声明的变量一旦完毕初始化,其它线程就能看到这个final变量。事实上,可见性事实上能够看成是一种机制,线程在进入/退出同步块程序时,它将发送/接收一个变量的更改。

③  有序性。有序性指在线程内看方法的运行,全部的指令都是有序的。都依照一种串行方式运行。而在线程内观察其它线程,全部指令都是无序的,指令都可能交叉运行。Java中提供了volatile和synchronized两个关键词保证线程之间操作的有序性。而这个有序性不过相对的,volatile禁止指令重排序,synchronized则保证持有同一个锁的同步块只能串行运行。

JMM能够说是Java的基础。它的定义将直接影响JVM及java多线程实现的机制,要想深入了解多线程问题相关的现象。正确Java内存模型的深入研究是必不可少的。

它的定义必须考虑到以下几个方面,一个是,如何更有效地提高该线程的性能效率。二是如何在底层物理硬件和操作系统的差异,提供统一的对外屏蔽的概念;最后,它是多么的严谨和轻松的典范。语义确保不会产生歧义和一些优化扩展。

对多线程java内存模型JMM的更多相关文章

  1. 多线程并发之java内存模型JMM

    多线程概念的引入是人类又一次有效压寨计算机的体现,而且这也是非常有必要的,因为一般运算过程中涉及到数据的读取,例如从磁盘.其他系统.数据库等,CPU的运算速度与数据读取速度有一个严重的不平衡,期间如果 ...

  2. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  3. Java内存模型JMM与可见性

    Java内存模型JMM与可见性 标签(空格分隔): java 1 何为JMM JMM:通俗地讲,就是描述Java中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这 ...

  4. 全面理解Java内存模型(JMM)及volatile关键字(转载)

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...

  5. 全面理解Java内存模型(JMM)及volatile关键字(转)

    原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...

  6. 什么是Java内存模型(JMM)

    什么是java内存模型 缓存一致性问题 在现代计算机中,因为CPU的运算速度远大于内存的读写速度,因此为了不让CPU在计算的时候因为实时读取内存数据而影响运算速度,CPU会加入一层缓存,在运算之前缓存 ...

  7. Java内存模型(JMM)详解

    在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...

  8. Java并发编程:Java内存模型JMM

    简介 Java内存模型英文叫做(Java Memory Model),简称为JMM.Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性. CPU和缓存一 ...

  9. java内存模型(JMM)和happens-before

    目录 重排序 Happens-Before 安全发布 初始化安全性 java内存模型(JMM)和happens-before 我们知道java程序是运行在JVM中的,而JVM就是构建在内存上的虚拟机, ...

随机推荐

  1. GO语言学习(十八)Go 语言接口

    Go 语言接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口. 实例 /* 定义接口 */ type interface ...

  2. GO语言学习(十二)Go 语言函数

    Go 语言函数 函数是基本的代码块,用于执行一个任务. Go 语言最少有个 main() 函数. 你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务. 函数声明告诉了编译器函数的名称,返回 ...

  3. groupbox里面添加Form

    /// <summary> /// 动态加载dll /// 反射 /// </summary> private void dynamicDll() { string dllNa ...

  4. Valgrind的用法

    Valgrind是执行在Linux上一套基于仿真技术的程序调试和分析工具,它包括一个内核──一个软件合成的CPU,和一系列的小工具,每一个工具都能够完毕一项任务──调试.分析,或測试等. Valgri ...

  5. 1.5 Python基础知识 - while循环

    在我们生活中有很多反复要做的事情,或者动作,我们称之为循环.在开发程序中也会有循环的事情要去做,就是需要反复的去执行某个代码,或者反复进行某种演算,直到达到某种条件的时候才会停止.在Python中我们 ...

  6. LeetCode Algorithm 06_ZigZag Conversion

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  7. JMeter--聚合报告之 90% Line 正确理解

    90% Line 参数正确的含义: 虽然,我的上面理解有一定的道理,显然它(90% 用户的响应时间)是错误的.那看看JMeter 官网是怎么说的? 90% Line - 90% of the samp ...

  8. 宏定义#define整理

    一.宏定义#define 优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率.代码可以写的通俗易懂.可以提高程序的清晰性.可读性,使于修改移植等. 缺点:宏定义的使用实 ...

  9. 数据结构-堆实现优先队列(java)

    队列的特点是先进先出.通常都把队列比喻成排队买东西,大家都非常守秩序,先排队的人就先买东西. 可是优先队列有所不同,它不遵循先进先出的规则,而是依据队列中元素的优先权,优先权最大的先被取出. 这就非常 ...

  10. 【z07】机器翻译

    [题目链接]:http://noi.qz5z.com/viewtask.asp?id=z07 [题解] 可以理解为一直往一个队列里面加东西: 然后每次查找一个东西在不在队列的最尾部长度为m的区间范围内 ...