问题描述
synchronized语句建立before-before关系。但我不确定细节。
在可以阅读
A synchronized statement establishes a happens-before relation. But im not sure about the details.In http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html one can read
我想知道我是否理解正确。因此,请看下面的例子。
让我们假设有2个线程T1,T2共享类Object的相同实例数据和Object类的对象。
现在,以下代码在给定的线程和顺序中执行:
I want to know if i understood that correctly. Therefore have a look at the following example.Lets assume that there are 2 Threads T1,T2 sharing the same instance data of a class Data and object of the class Object.Now the following code gets executed in the given threads and order:
(1)T1: data.setValue("newValue");
(2)T1: synchronized(object){}
(3)T2: synchronized(object){}
(4)T2: String str=data.getValue();
因为(1)和(2)在同一个线程中执行,一个有hb(1, 2)和类似物hb(3,4)。在(2)中是监视器的解锁和(3)同一监视器的锁定,因此hb(2,3),因此hb(1,4)和str应该等于newValue。那是对的吗?如果不是hb(2,3)应该是错的,为什么?
because (1) and (2) are executed in the same thread, one has hb(1,2) and analogue hb(3,4). In (2) is an unlock of the monitor and in (3) a lock of the same monitor, thus hb(2,3), therefore hb(1,4) and str should be equal to "newValue". Is that correct? If not than hb(2,3) should be wrong, but why?
编辑
因为需要详细的类数据来回答这个问题:
Because details of the class Data is needed to answer the question:
public class Data {
private String value
public void setValue(String newValue){
value=newValue;
}
public String getValue getValue(){
return value;
}
}
编辑2
清楚,那个不能保证执行的顺序。当一个人改为
Edit 2its clear, that one cannot guarantee the order of execution. When one has instead
(1*)T1: synchronized(object){data.setValue("newValue");}
(2*)T2: synchronized(object){String str=data.getValue();}
一个也不能保证(1 *)在(2 *)之前被激活,但是如果我是正确的,那么一个人保证在(2 *)之后有一个str =newValueif(1) *)在(2 *)之前执行。我想知道第一个例子是否相同
one has also no guarantee that (1*) is exectuted before (2*), but if im right, one has the guarantee that after (2*) one has str= "newValue" if (1*) was executed before (2*). I want to know if the same holds for the 1st example
推荐答案
是的,您的逻辑对于此特定方案是正确的。如果(且仅当) 2
在 3
之前执行,那么 hb(2,3)
。要理解它应该是什么,想象一个线程过程,如下所示:
Yes, your logic is correct for this specific scenario. If (and only if) 2
executes before 3
then hb(2, 3)
. To understand why it should be, imagine a thread process such as the following:
localState *= 2;
synchronized(object) {
sharedState = localState;
}
虽然 localState
是计算外部一个同步块,其他线程应该有必要看到这个计算还看到 sharedState 。
Although
localState
is computed outside a synchronized block, it should be necessary for other threads to see this computation to also see the correct value for sharedState
.
然而,重要的是要理解没有理由期待您所询问的订单作为结果。例如,执行这种方式很容易:
However, it's important to understand that there is no reason to expect the order you've asked about as the outcome. For example it could just as easily happen to execute this way:
(1)T1: data.setValue("newValue");
(3)T2: synchronized(object){}
(4)T2: String str=data.getValue();
(2)T1: synchronized(object){}
这很糟糕,因为现在
T1
正在写入内存中的某个位置而没有同步,而 T2
即将读取它。 ( T2
甚至可以在写入的同时读取!)
This is bad because now
T1
is writing to a location in memory without synchronization while T2
is about to read it. (T2
could even read at the same time the write is occurring!)
要了解发生了什么 - 之前就是这样,相反,想象这些线程并发运行(如线程所做)并在以下时间轴下执行:
To understand what happens-before is all about, instead imagine these threads are running concurrently (as threads do) and execute under the following timeline:
| T1 | T2
-------------------------------------------------------------
1 | synchronized(object){} |
2 | data.setValue("newValue"); | String str=data.getValue();
3 | | synchronized(object){}
请注意我如何对齐这些假设行为。
Notice how I've aligned these hypothetical actions.
- 在
1
点,T1
获取锁定并将其释放。 - 点
2
,T1
同时执行写入T2
执行读取。 - 点
3
,T2
获取锁并将其释放。
At point
1
,T1
acquires the lock and releases it.At point
2
,T1
executes a write while simulaneouslyT2
executes a read.At point
3
,T2
acquires the lock and releases it.
但实际上先发生
2
? T1
的写或 T2
的读?
同步不保证线程实际相对于彼此执行的顺序。相反,它是关于线程之间的内存一致性。
Synchronization doesn't guarantee the order that threads actually execute with respect to one another. Instead, it is about memory consistency between threads.
点
2
,因为没有同步,即使 T1
实际上在之前写 T2
读取它, T2
可以自由查看内存中的旧值。因此,它出现 T2(2)
发生在 T1(2)
之前。
At point
2
, because there is no synchronization, even if T1
actually makes the write before T2
reads it, T2
is free to see the old value in memory. Therefore it can appear that T2(2)
happened before T1(2)
.
从技术上讲,这意味着在同步之外,线程可以在CPU缓存而不是主存储器中自由读/写。同步强制主存储器中的读/写。
Technically what this means is that outside of synchronization, a thread is free to read/write in a CPU cache instead of main memory. Synchronization forces the read/write in main memory.
现在使用第二个并发时间线:
Now with the second concurrent timeline:
T1 | T2
------------------------------------------------------------
synchronized(object){ | synchronized(object){
data.setValue("newValue"); | String str=data.getValue();
} | }
虽然我们无法保证哪个线程首先获得锁定,但我们确保内存访问将保持一致。我们也保证他们的行为不会重叠,这在第一个时间表中是可能的。
Although we do not have a guarantee about which thread acquires the lock first, we do have a guarantee that the memory access will be consistent. We also have a guarantee that their actions will not overlap, which was possible in the first timeline.
- 如果
T1
首先获得锁定,保证T1
的同步动作将显示为在T2 的行动。 (
T1
肯定会在T2
读取之前写入。) 如果
的行动。 (T2
首先获得锁定,保证T2
的同步动作看起来好像发生在 T1T1
肯定会在T2
读取后写入。)
If
T1
acquires the lock first, it is guaranteed thatT1
's synchronized actions will appear as if happening beforeT2
's actions. (T1
will definitely write beforeT2
reads.)If
T2
acquires the lock first, it is guaranteed thatT2
's synchronized actions will appear as if happening beforeT1
's actions. (T1
will definitely write afterT2
reads.)
这篇关于Java同步并发生在之前的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!