java内存模型概述_Java内存模型-快速概述和注意事项

java内存模型概述

在计算中, 内存模型描述了线程如何通过内存交互,或更一般地,它指定了为分段内存或分页内存平台生成代码时允许编译器进行的假设。 在给定程序和该程序的执行跟踪的情况下,它实质上描述了执行跟踪是否是该程序的合法执行。

Java内存模型描述了Java编程语言中的线程如何通过内存进行交互。 连同代码的单线程执行的描述一起,内存模型提供了Java编程语言的语义。 最初的Java内存模型开发于1995年,人们普遍认为它已损坏,从而阻止了许多运行时优化,并且没有为代码安全性提供足够有力的保证。 它通过Java社区流程进行了更新,即Java规范请求133(JSR-133) ,该规范于2004年对Tiger(Java 5.0)生效。

您可以在Java语言规范的“ 线程和锁 ”一章以及此Java内存模型讨论页面中找到一些非常有用的信息。

现在让我们来看看我们最新的JCG合作伙伴 Manoj在“ The Khangaonkar Report ”中提供的一些见解。

(注意:对原始帖子进行了少量编辑以提高可读性)

Java内存模型描述了定义多个线程写入和读取变量时如何看待写入内存的规则。

当线程读取变量时,不一定从内存中获取最新值。 处理器可能返回一个缓存的值。 此外,即使程序员在编写代码时先写入变量,然后读取变量,但只要编译器不改变程序语义,就可以对其重新排序。 处理器和编译器这样做通常是为了优化性能。 结果,线程可能看不到它期望看到的值。 这可能导致难以修复并发程序中的错误。

Java编程语言提供了“ synchronized”,“ volatile”和“ final”关键字来帮助编写安全的多线程代码。 但是,由于内存模型未指定,Java的早期版本存在一些问题。 JSR 133(Java内存模型和线程规范修订版)修复了早期内存模型中的某些缺陷。

大多数程序员都熟悉这样一个事实,即进入同步块意味着在监视器上获得锁定,以确保没有其他线程可以进入同步块。 不那么熟悉但同样重要的事实是

(1)获取锁并输入同步块会强制线程从内存刷新数据。
(2)退出同步块后,写入的数据将刷新到内存中。

这确保了同步块中的线程所写的值对于同步块中的其他线程可见。

有没有听说过Java上下文中的“ 发生在……之前 ”? JSR 133引入了“之前发生”一词,并为程序中动作的顺序提供了一些保证。 这些保证是:

(1)线程中的每个动作都在该线程之后的所有其他动作之前发生。
(2)显示器上的解锁发生在同一显示器上的后续锁定之前
(3)对变量的易失性写入发生在对同一变量的后续易失性读取之前 (4)对Thread.start()的调用发生在该线程中的任何其他语句之前 (5)线程中的所有动作在该线程上的其他任何线程从join()返回之前发生

术语“动作”在Java语言规范的17.4.2节中定义为可以被其他线程检测或影响的语句。 正常的读/写,易失性的读/写,锁定/解锁是一些动作。

规则1、4和5保证在单个线程中,所有动作将按照它们在创作程序中出现的顺序执行。 规则2和4确保在处理共享数据的多个线程之间,保持同步块的相对顺序以及对易失变量的读/写顺序。

规则2和4使volatile非常类似于同步块。 在JSR 133之前,volatile仍然意味着对volatile变量的写操作直接写到内存中,而读操作则从内存中读取。 但是编译器可能会对非易失性读/写进行重新排序,而非易失性读/写会导致错误的结果。 在JSR 133之后无法使用。

还有一点值得注意。 这与在类的构造函数中初始化的最终成员有关。 只要构造函数正确完成执行,其他线程就可以看到最终成员而无需同步。 但是,如果您从构造函数中共享对对象的引用,则所有选择都将关闭。

提出的规范描述了线程,锁,易失性变量和数据竞争的语义。 这包括所谓的Java内存模型

相关文章:


翻译自: https://www.javacodegeeks.com/2011/02/java-memory-model-quick-overview-and.html

java内存模型概述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值