最近看了两篇博文:
主题:java线程安全总结
主题:线程安全总结(二)
看完之后对自己触动很大,和自己以前的理解有很大的矛盾.当时发站内信给作者的疑惑内容如下:
写道
看完之后,有2个疑问:
⒈java内存模型,没有说内存模型的具体结构,如:heap,java stack,method area等.
2.关于"那么,何谓可见性? 多个线程之间是不能互相传递数据通信的,它们之间的沟通只能通过共享变量来进行。Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限制的。当线程操作某个对象时,执行顺序如下:
(1) 从主存复制变量到当前工作内存 (read and load)
(2) 执行代码,改变共享变量值 (use and assign)
(3) 用工作内存数据刷新主存相关内容 (store and write) JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write。当一个共享便变量在多个线程的工作内存中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值,这就是多线程的可见性问题。"
疑问:为什么要有很多的副本呢?然后再刷新到主存呢?这样做不是效率很低?
java中的方法是值传递,参数是对象的话,只是对象指针的一个副本,如:
public void fun(Object obj){
// 改变obj的属性
obj.property = "abc";
// 改变obj指针的值,对方法外面的obj无影响
obj = new Object();
obj.property = "def";
}
既然每个线程中java stack传递的都是指针(指向heap内的对象),为什么还要复制一个heap内对象的副本呢?
后来看到第二篇的时候
写道
看完之后明白了,我以前的理解只是基于内存中的模型,而你说的read,load,use,assign,store,write针对的是对CPU,寄存器,内存等统一抽象的工作内存的操作
谢谢分享!让我对线程安全的理解更深入一步
今天,特意的查询了这方面的内容,博客地址:http://kenwublog.com/illustrate-memory-reordering-in-cpu
写道
对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存(caching)能够从数量级上降低内存延迟的成本这些缓存为了性能重新排列待定内存操作的顺序。也就是说,程序的读写操作不一定会按照它要求处理器的顺序执行。
重排序的背景
我们知道现代CPU的主频越来越高,与cache的交互次数也越来越多。当CPU的计算速度远远超过访问cache时,会产生cache wait,过多的cache wait就会造成性能瓶颈。
针对这种情况,多数架构(包括X86)采用了一种将cache分片的解决方案,即将一块cache划分成互不关联地多个 slots (逻辑存储单元,又名 Memory Bank
或 Cache Bank),CPU可以自行选择在多个 idle bank 中进行存取。这种 SMP
的设计,显著提高了CPU的并行处理能力,也回避了cache访问瓶颈。
Memory Bank的划分
一般 Memory bank 是按cache address来划分的。比如 偶数adress 0×12345000 分到 bank 0, 奇数address 0×12345100 分到 bank1。
重排序的种类
编译期重排。编译源代码时,编译器依据对上下文的分析,对指令进行重排序,以之更适合于CPU的并行执行。
运行期重排,CPU在执行过程中,动态分析依赖部件的效能,对指令做重排序优化。
实例讲解指令重排序原理
为了方便理解,我们先来看一张CPU内部结构图。
从图中可以看到,这是一台配备双CPU的计算机,cache 按地址被分成了两块 cache banks,分别是 cache bank0
和 cache bank1
。
最后引用博客作者的一句话:
写道
先抛开java虚拟机不谈,我们都知道,现在的计算机,cpu在计算的时候,并不总是从内存读取数据,它的数据读取顺序优先级是:寄存器-高速缓存-内存。线程耗费的是CPU,线程计算的时候,原始的数据来自内存,在计算过程中,有些数据可能被频繁读取,这些数据被存储在寄存器和高速缓存中,当线程计算完后,这些缓存的数据在适当的时候应该写回内存。当个多个线程同时读写某个内存数据时,就会产生多线程并发问题,涉及到三个特性:原子性,有序性,可见性
而实现这个的就是编译期重排和运行时重排序
分享到:
相关推荐
Java并发编程是Java语言中最为复杂且重要的部分之一,它涉及了多线程编程、内存模型、同步机制等多个领域。为了深入理解Java并发编程,有必要了解其核心技术点和相关实现原理,以下将详细介绍文件中提及的关键知识点...
- **使用并发原语** 例如`java.util.concurrent.atomic`包中的原子变量,可以提供轻量级的线程安全。 通过这些笔记,我们可以了解到Java并发编程中的关键概念和实践,对于理解和编写高效的并发代码具有极大的帮助...
除了上述关键字,Java还提供了其他并发工具类,如java.util.concurrent包下的Atomic类,它们提供了原语级别的原子操作,如AtomicInteger、AtomicLong等,适用于更新整数或长整型变量,而不需要使用锁。 此外,理解...
《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java多线程编程技术的权威著作。这本书详细阐述了在Java平台中进行高效并发处理的关键概念、设计原则和实用模式。以下是对该书内容的一些核心知识点的概述...
- **并发模型**:Java采用基于共享内存的并发模型,线程间通过共享变量进行通信,同时提供了同步机制防止数据竞争。 2. **同步控制** - **同步原语**:包括`synchronized`关键字、`volatile`关键字、`Lock`接口...
7. **同步原语**(07章):深入解析Java内存模型(JMM)和同步原语,包括volatile、synchronized以及Lock接口,如ReentrantLock和ReadWriteLock。 8. **并发设计模式**(08章):介绍在并发编程中常见的设计模式,...
《cpp-ck并发原语安全内存回收机制和非阻塞数据结构》 在现代计算机系统中,多线程和并发编程已经成为提升效率的关键技术。cpp-ck是一个专门为C++开发者设计的并发库,它提供了丰富的并发原语,安全的内存回收机制...
Java内存屏障与JVM并发详解实用 Java内存屏障是java并发编程中的一种机制,用于确保多线程程序的正确执行。它通过强制处理器顺序执行内存操作,从而避免了内存屏障带来的问题。在本文中,我们将深入探讨Java内存...
- **线程与进程**:线程是操作系统分配CPU时间的基本单位,而进程则包含多个线程,拥有独立的内存空间。 - **Java中的线程创建**:通过`Thread`类的实例化或者实现`Runnable`接口来创建线程。 - **守护线程...
《Java并发编程实战》是Java开发者必读的经典书籍之一,它深入浅出地探讨了Java平台上的并发编程技术。这本书不仅提供了理论知识,还包含了大量实际应用案例和源码,帮助读者更好地理解和掌握多线程编程的核心概念。...
《Java并发编程实践》是一本深入探讨Java平台上的并发编程的经典著作。这本书旨在帮助开发者理解和掌握如何有效地编写多线程程序,以充分利用现代处理器的多核能力,提高应用程序的性能和响应性。以下是对该书内容的...
4. **原子操作与CAS**:`java.util.concurrent.atomic`包中的原子变量类如`AtomicInteger`提供了无锁编程的能力。比较和交换(CAS)操作是其底层实现的关键,理解CAS的工作原理可以帮助你编写更高效的并发代码。 5....
Java自带的并发框架通过提供高级的并发工具和类,使开发者能够更安全、更高效地编写多线程程序,避免了直接操作底层并发原语带来的复杂性和潜在风险。通过理解和熟练使用这些工具,我们可以构建出更健壮、更具伸缩性...
本书首先介绍了并发的基本概念,如线程、进程、同步与通信,以及Java内存模型(JMM)的基础知识,这些都是理解和编写正确并发代码的基础。 接着,书中详细讲解了Java中的线程管理,包括如何创建和控制线程,以及...
- 分析并发性能,如CPU使用率、内存占用、响应时间等,使用`JVisualVM`或其他监控工具进行监控。 在文档“高并发隔离.docx”中,可能详细介绍了如何构建一个模拟环境,包括如何设置线程池大小,如何构造并发任务,...
《JAVA并发编程实践》是一本深入探讨Java并发编程的权威指南,专为那些希望充分利用多核处理器性能,提升系统效率的开发者设计。这本书由Brian Goetz等多位Java并发领域的专家共同编写,它不仅介绍了Java并发的基本...
总的来说,这个实验旨在让学生通过实践来掌握操作系统中的并发控制机制,特别是信号量机制的关键组件——P(s)和V(s)原语。这样的实践性学习有助于提升学生的理论与实践结合能力,为他们未来在操作系统设计与分析等...
- **volatile**:保证共享变量的可见性和禁止指令重排序,使得所有线程能获取到最新值。 - **CAS(Compare and Swap)**:无锁算法,原子性地比较并更新内存位置的值,常用于实现原子变量。 3. **线程安全** - *...
与《高性能Java系统实现与调优.pdf》这本书结合,你可能会学到更多关于Java性能优化的技巧,包括内存管理、垃圾回收、JVM参数调整等方面。书中的内容可能涵盖了如何通过调整系统配置、优化算法和数据结构,以及使用...