且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java 内存模型 - 有人可以解释一下吗?

更新时间:2023-11-09 22:42:28

我不会在这里尝试实际回答您的问题 - 相反,我会将您重定向到我推荐的关于此主题的建议书:Java 并发实践.

I'm not going to attempt to actually answer your questions here - instead I'll redirect you to the book which I seeing recommended for advice on this topic: Java Concurrency in Practice.

一个警告:如果这里有个答案,估计其中不少是错误的.我不打算发布详细信息的原因之一是因为我很确定至少在某些方面是错误的.当我说每个认为他们可以回答这个问题的人实际上有足够的严谨性来做对的可能性几乎为零时,我的意思是对社区没有任何不尊重.(Joe Duffy 最近发现了一些 .NET 内存模型,很惊讶.如果他能搞错,我们这样的凡人也能搞错.)

One word of warning: if there are answers here, expect quite a few of them to be wrong. One of the reasons I'm not going to post details is because I'm pretty sure I'd get it wrong in at least some respects. I mean no disrespect whatsoever to the community when I say that the chances of everyone who thinks they can answer this question actually having enough rigour to get it right is practically zero. (Joe Duffy recently found a bit of the .NET memory model that was surprised by. If he can get it wrong, so can mortals like us.)

我将仅就一个方面提供一些见解,因为它经常被误解:

I will offer some insight on just one aspect, because it's often misunderstood:

易变性和原子性是有区别的.人们通常认为原子写入是易失性的(即,如果写入是原子的,则无需担心内存模型).这不是真的.

There's a difference between volatility and atomicity. People often think that an atomic write is volatile (i.e. you don't need to worry about the memory model if the write is atomic). That's not true.

波动性是关于一个线程执行读取(逻辑上,在源代码中)是否会看到"另一个线程所做的更改.

Volatility is about whether one thread performing a read (logically, in the source code) will "see" changes made by another thread.

原子性是关于如果看到更改,是否有可能只看到更改的一部分.

Atomicity is about whether there is any chance that if a change is seen, only part of the change will be seen.

例如,写入一个整数字段.这保证是原子的,但不是易失性的.这意味着如果我们有(从 foo.x = 0 开始):

For instance, take writing to an integer field. That is guaranteed to be atomic, but not volatile. That means that if we have (starting at foo.x = 0):

Thread 1: foo.x = 257;
Thread 2: int y = foo.x;

y 可能是 0 或 257.由于原子性约束,它不会是任何其他值(例如 256 或 1).但是,即使您知道在墙时"线程 2 中的代码在线程 1 中的代码之后执行,也可能存在奇怪的缓存、内存访问移动"等.使变量 x 易失会解决这个问题.

It's possible for y to be 0 or 257. It won't be any other value, (e.g. 256 or 1) due to the atomicity constraint. However, even if you know that in "wall time" the code in thread 2 executed after the code in thread 1, there could be odd caching, memory accesses "moving" etc. Making the variable x volatile will fix this.

剩下的交给真正的诚实至善的专家.

I'll leave the rest up to real honest-to-goodness experts.