`
chentianliang
  • 浏览: 15524 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java线程安全总结(二)

阅读更多
   站内很多人都问我,所谓线程的“工作内存”到底是个什么东西?有的人认为是线程的栈,其实这种理解是不正确的。看看JLS(java语言规范)对线程工作内存的描述,线程的working memory只是cpu的寄存器和高速缓存的抽象描述。
      可能 很多人都觉得莫名其妙,说JVM的内存模型,怎么会扯到cpu上去呢?在此,我认为很有必要阐述下,免得很多人看得不明不白的。先抛开java虚拟机不谈,我们都知道,现在的计算机,cpu在计算的时候,并不总是从内存读取数据,它的数据读取顺序优先级是:寄存器-高速缓存-内存。线程耗费的是CPU,线程计算的时候,原始的数据来自内存,在计算过程中,有些数据可能被频繁读取,这些数据被存储在寄存器和高速缓存中,当线程计算完后,这些缓存的数据在适当的时候应该写回内存。当个多个线程同时读写某个内存数据时,就会产生多线程并发问题,涉及到三个特性:原子性,有序性,可见性。在《线程安全总结》这篇文章中,为了理解方便,我把原子性和有序性统一叫做“多线程执行有序性”。支持多线程的平台都会面临这种问题,运行在多线程平台上支持多线程的语言应该提供解决该问题的方案。
       那么,我们看看JVM,JVM是一个虚拟的计算机,它也会面临多线程并发问题,java程序运行在java虚拟机平台上,java程序员不可能直接去控制底层线程对寄存器高速缓存内存之间的同步,那么java从语法层面,应该给开发人员提供一种解决方案,这个方案就是诸如 synchronized, volatile,锁机制(如同步块,就绪队列,阻塞队列)等等。这些方案只是语法层面的,但我们要从本质上去理解它,不能仅仅知道一个 synchronized 可以保证同步就完了。   在这里我说的是jvm的内存模型,是动态的,面向多线程并发的,沿袭JSL的“working memory”的说法,只是不想牵扯到太多底层细节,因为 《线程安全总结》这篇文章意在说明怎样从语法层面去理解java的线程同步,知道各个关键字的使用场景。



      今天有人问我,那java的线程不是有栈吗?难道栈不是工作内存吗?工作内存这四个字得放到具体的场景中描述,方能体现它具体的意义,在描述JVM的线程同步时,工作内存指的是寄存器和高速缓存的抽象描述,具体请自行参阅JLS。上面讲的都是动态的内存模型,甚至已经超越了JVM的范围,那么JVM的内存静态存储是怎么划分的?今天还有人问我,jvm的内存模型不是有eden区吗?也不见你提起。我跟他说,这是两个角度去看的,甚至是两个不同的范围,动态的线程同步的内存模型,涵盖了cpu,寄存器,高速缓存,内存;JVM的静态内存模型只是一种对内存的物理划分而已,它只局限在内存,而且只局限在JVM的内存。那些什么线程栈,eden区都仅仅在JVM内存。
      说说JVM的线程栈和有个朋友反复跟我纠结的eden区吧。JVM的内存,被划分了很多的区域:

1.程序计数器
每一个Java线程都有一个程序计数器来用于保存程序执行到当前方法的哪一个指令。
2.线程栈
线程的每个方法被执行的时候,都会同时创建一个帧(Frame)用于存储本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果VM栈可以动态扩展(VM Spec中允许固定长度的VM栈),当扩展时无法申请到足够内存则抛出OutOfMemoryError异常。
3.本地方法栈
4.堆
每个线程的栈都是该线程私有的,堆则是所有线程共享的。当我们new一个对象时,该对象就被分配到了堆中。但是堆,并不是一个简单的概念,堆区又划分了很多区域,为什么堆划分成这么多区域,这是为了JVM的内存垃圾收集,似乎越扯越远了,扯到垃圾收集了,现在的jvm的gc都是按代收集,堆区大致被分为三大块:新生代,旧生代,持久代(虚拟的);新生代又分为eden区,s0区,s1区。新建一个对象时,基本小的对象,生命周期短的对象都会放在新生代的 eden区中,eden区满时,有一个小范围的gc(minor gc),整个新生代满时,会有一个大范围的gc(major gc),将新生代里的部分对象转到旧生代里。
5.方法区
其实就是永久代(Permanent Generation),方法区中存放了每个Class的结构信息,包括常量池、字段描述、方法描述等等。VM Space描述中对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存,也可以选择固定大小或者可扩展外,甚至可以选择不实现垃圾收集。相对来说,垃圾收集行为在这个区域是相对比较少发生的,但并不是某些描述那样永久代不会发生GC(至少对当前主流的商业JVM实现来说是如此),这里的GC主要是对常量池的回收和对类的卸载,虽然回收的“成绩”一般也比较差强人意,尤其是类卸载,条件相当苛刻。
6.常量池
Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量表(constant_pool table),用于存放编译期已可知的常量,这部分内容将在类加载后进入方法区(永久代)存放。但是Java语言并不要求常量一定只有编译期预置入 Class的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的String.intern()方法)。



关于垃圾收集,在此不多说,留到垃圾收集那一章再详细说吧。关于java的同步,其实还有基于CPU原语的比较并交换的非阻塞算法(CAS),不过这个在java的并发包里已经实现了很多,因此关于这点,就留到java并发包那一章介绍吧。后面我会专门写一篇文章,JVM内存与垃圾收集。
来源:http://www.iteye.com/topic/808550


分享到:
评论

相关推荐

    java线程安全总结.doc

    以下是对Java线程安全的深入总结: ### 一、线程安全的定义 线程安全是指当多个线程访问同一块代码时,如果每个线程都能得到预期的结果,且不产生数据不一致或同步问题,那么这块代码就被称为线程安全的。Java中的...

    java线程安全总结

    java线程安全总结 帮助你们更好的理解什么是线程 什么是网络安全

    java线程安全总结.pdf

    标题“java线程安全总结.pdf”指向了文档的主要内容:这是关于Java编程语言中的线程安全问题的总结性资料。线程安全是并发编程中的一个核心概念,它与Java多线程技术紧密相关。文档的描述信息非常简洁,只是重复了...

    java多线程编程总结

    #### 二、Java线程:创建与启动 - **定义线程** 1. 扩展 `java.lang.Thread` 类。此类中有一个 `run()` 方法,该方法需要特别注意其使用方式: ```java public void run() ``` 如果线程是使用独立的 `Runnable...

    java线程安全总结.doc下载

    Java线程安全是多线程编程中的一个核心概念,尤其在服务器端开发中,理解并掌握线程安全至关重要。线程安全是指当多个线程访问一个对象时,如果这个对象的状态始终保持一致,那么我们就说这个对象是线程安全的。在...

    java线程安全性总结

    用思维导图将Java线程安全性相关基本概念联系起来

    Java多线程编程总结

    #### 二、Java线程:创建与启动 1. **定义线程** - **扩展 `java.lang.Thread` 类**:此类包含一个 `run()` 方法,子类应重写此方法。 - **实现 `java.lang.Runnable` 接口**:创建实现了 `Runnable` 接口的对象...

    java线程安全总结[汇编].pdf

    Java线程安全是多线程编程中的一个核心概念,...总结起来,Java线程安全是一个复杂而又重要的主题,涉及到多线程编程中的各种机制和策略。理解并掌握这些知识点,可以帮助开发者编写出高效、稳定、线程安全的Java程序。

    Java线程安全问题_动力节点Java学院整理

    其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性。我们都知道计算机有高速缓存...

    Java多线程知识点总结

    Java提供了多种机制来保证线程安全,比如使用synchronized关键字来同步方法或代码块,实现线程之间的同步。当一个线程试图进入一个已经被另一个线程持有的同步代码块时,它将进入阻塞状态,直到同步代码块的执行线程...

    Java多线程的总结

    Java集合框架中有一些线程安全的类,如Vector、HashTable、ConcurrentHashMap等,它们内部实现了同步机制,可以在多线程环境中直接使用,避免了手动同步的复杂性。 十、线程局部变量 ThreadLocal为每个线程都创建了...

    Java线程知识总结

    Java线程知识是Java开发中不可或缺的部分,尤其在构建高性能、高并发的应用程序时显得尤为重要。线程允许程序在同一时间处理多个任务,提高了CPU的利用率和程序的响应速度。 在Java中,线程是由Java虚拟机(JVM)...

    JAVA多线程总结

    **二、Java线程:创建与启动** 1. **定义线程**: - 继承Thread类并重写run()方法。 - 实现Runnable接口,并在run()方法中定义线程行为。 2. **实例化线程**: - 对于Thread类的子类,直接new一个实例。 - ...

    Java线程详细总结

    ### Java线程详细总结 #### 一、Java线程简介 Java中的线程是一个轻量级的进程,它能够在一个程序中并发地执行多个任务。Java语言直接支持线程的概念,这使得Java成为多线程编程的理想选择。与进程相比,线程具有...

    Java 多线程 订票 示例 线程安全

    总结起来,Java多线程在实现订票系统时,需要注意线程安全问题,通过合理使用同步机制、Lock接口和原子类,可以在保证数据一致性的同时提高并发性能。在实际开发中,要根据业务场景选择合适的线程安全策略,以达到...

    java 多线程设计模式 进程详解

    《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口的线程 线程的生命周期 线程命名 ...

Global site tag (gtag.js) - Google Analytics