Java中synchronized关键字的记忆效应 [英] Memory effects of synchronized keyword in Java

查看:137
本文介绍了Java中synchronized关键字的记忆效应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

之前可能已经回答过,但由于问题的复杂性,我需要确认。所以我重新解释了这个问题

This might have been answered before, but because of the complexity of the issue, I need a confirmation. So I rephrase the question

问题1 :当线程进入同步块时,内存屏障将包含所触及的任何字段,而不仅仅是字段我同步的对象?因此,如果在同步块内修改了许多对象,则在线程内存缓存之间会有大量内存移动。

Question 1 : When a thread enters a synchronized block, the memory barrier will include any fields touched, not just fields of the object that I synchronized on? So if many many objects are modified inside a synchronized block, that's a lot of memory moves between thread memory caches.

Thread 1
object.field1 = "";
synchronized (lock) {
  farAwayObject.field1 = "";
  farAwayObject.evenFarther.field2 = "";
}

Thread 2. assuming thread ordering is correct
synchronized (lock) {
  //thread 2 guaranteed to see all fields above as ""
  //even object.field1 ?
}

问题2 object.field1 =; 在线程1隐式部分发生在之前的关系?

Question 2 : Is object.field1 = ""; in thread 1 implicitly part of the happens-before relationship?

我希望它是但它可能不会。如果没有,是否有一个技巧,使它没有把它放入同步块?很难在程序上另外说
并且将所有内容放在synchronized {}下是不切实际的。

I hope it is but It might not. If not is there a trick to make it so without putting it into the sync block? It is hard to reason on the program otherwise and it is not practical to put everything under the synchronized { }.

编辑:澄清:object.field1是不易变,问题是将线程2保证看到线程1的写入,至少。我的问题是内存可见性。为了论证,假设只有线程1写入非易失性object.field1。

clarification: object.field1 is not volatile and the question is "will thread 2 guaranteed to see the write of thread 1, at least ". My question is about memory visibility. For the sake of the argument, let's say only thread 1 writes to non volatile object.field1.

问题2可以改写

是否会同步阻止在同一个锁上同步的其他线程看到之前的锁定推送更改?

"Will a synchronized block on a lock push changes made before to be seen by other threads synchronizing on the same lock? "

推荐答案


当线程进入同步块时,内存屏障将为
包括所触及的任何字段,而不仅仅是在
上同步的对象字段

When a thread enters a synchronized block, the memory barrier will include any fields touched, not just fields of the object that I synchronized on

假设 farAwayObject evenFarther 的字段总是通过获取来修改和加入在应用程序周围的同一对象上有一个 lock ,所有线程将始终看到对 farAwayObject 和<$的更新c $ c> evenFarther ,因为 synchronized 强制执行发生前条件。

Assuming that the fields of farAwayObject and evenFarther are always modified and accesed by obtaining a lock on the same object all around your application, all threads will always see the updates made to farAwayObject and evenFarther since synchronized enforces a happens-before condition.


//线程2保证看到上面的所有字段为

对于 object.field1 ,不知道如何声明它是不可能的。假设 field1 是一个未标记为 volatile 的引用,它将不会是之前发生的一部分关系和线程可能会看到它的陈旧值。

The same cannot be said for object.field1 without knowing how it was declared. Assuming that field1 is a reference not marked as volatile, it will not be a part of the happens before relationship and threads may see stale values for it.


我希望它是,但它可能没有。如果不是有一个技巧可以使它变成
而不将它放入同步块?

I hope it is but It might not. If not is there a trick to make it so without putting it into the sync block?

是的。将 object.field1 标记为 volatile

添加您的编辑:


问题2可以改为:

The question 2 can be rephrased as

锁定推送上的同步块是否会在同一个同步的其他线程看到之前变为
锁定?

"Will a synchronized block on a lock push changes made before to be seen by other threads synchronizing on the same lock? "

AFAIK答案是肯定的,前提是写线程在读取线程之前获取锁定。不幸的是,这是你通常无法保证的,这就是为什么 object.field1 需要标记为 volatile 语句需要在 synchronized 块内移动。

AFAIK the answer is Yes, provided that the writing threads acquire the lock before the reading threads. Unfortunately, this is something you generally can't guarantee and that's why object.field1 needs to be marked as volatilethe statement needs to moved inside the synchronized block.

看一下 JSR 133 ,其中讨论了当缓存被刷新到主内存时线程退出一个同步的块。这应该进一步澄清事情。

Take a look at JSR 133 which talks about the cache being flushed to main memory when the thread exits a syncronized block. This should clarify things further.

这篇关于Java中synchronized关键字的记忆效应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆