Eug*_*ene 2 java multithreading jit jvm locking
我正在查看我发现的最简单的示例之一,并开始推理SO(同步顺序)或更准确地说,缺乏同步顺序。考虑下面的例子:
int a, b; // two shared variables
Thread-X:
void threadX() {
synchronized(this) {
a = 1;
}
synchronized(this) {
b = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个读者线程Thread-Y:
void threadY() {
int r1 = b;
int r2 = a;
}
Run Code Online (Sandbox Code Playgroud)
为了简单起见,我们假设Thread-Y完全按照这个顺序进行读取:它肯定会先读取b然后再读取a(与写入相反)。
允许读取线程查看[1, 0](就像之前b=1发生的那样)。我想我也理解为什么:因为两个操作之间没有同步顺序,因此没有发生之前,并且根据这是一个数据竞争: a=1JLS
当程序包含两个不按先发生关系排序的冲突访问时,我们称其包含数据争用。
因此,读a和b是两个活泼的读法,所以看到b=1和a=0是允许的和可能的。
现在这又允许 JVM 在 writer 中进行锁粗化,因此它变成:
void threadX() {
synchronized(this) {
a = 1;
b = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果读者最初是这样写的:
void threadY() {
synchronized(this) {
int r1 = b;
}
synchronized(this) {
int r2 = a;
}
}
Run Code Online (Sandbox Code Playgroud)
仍然允许锁粗化吗?我想我知道答案,但我也想听到一个有根据的解释。
小智 7
是的,这是允许的。
这是一个简单的解释。
请记住synchronized块:
synchronized当另一个线程持有相同的锁时,线程无法进入块synchronized中完成的所有操作synchronized换句话说,synchronized块总是按照全局顺序自动执行。不同的执行在块的交错方式上可能有所不同synchronized,但情况总是如此:
synchronized块threadX()总是在第二个块之前执行synchronized与来自的块相同threadY()有 6 种可能的交错:
threadX threadY threadX threadY threadX threadY
------------------------------- ------------------------------- -------------------------------
synchronized { | synchronized { | synchronized { |
a = 1; | a = 1; | a = 1; |
} | } | } |
synchronized { | | synchronized { | synchronized {
b = 1; | | int r1 = b; | int r1 = b;
} | | } | }
| synchronized { synchronized { | | synchronized {
| int r1 = b; b = 1; | | int r2 = a;
| } } | | }
| synchronized { | synchronized { synchronized { |
| int r2 = a; | int r2 = a; b = 1 |
| } | } } | }
(Case A) (Case B) (Case C)
threadX threadY threadX threadY threadX threadY
------------------------------- ------------------------------- -------------------------------
| synchronized { | synchronized { | synchronized {
| int r1 = b; | int r1 = b; | int r1 = b;
| } | } | }
| synchronized { synchronized { | synchronized { |
| int r2 = a; a = 1; | a = 1; |
| } } | } |
synchronized { | | synchronized { synchronized { |
a = 1; | | int r2 = a; b = 1; |
} | | } } |
synchronized { | synchronized { | | synchronized {
b = 1; | b = 1; | | int r2 = a;
} | } | | }
(Case D) (Case E) (Case F)
Run Code Online (Sandbox Code Playgroud)
当您合并synchronized以下块时threadY():
void threadY() { void threadY() {
synchronized(this) { synchronized(this) {
int r1 = b; int r1 = b;
} => int r2 = a;
synchronized(this) { }
int r2 = a; }
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您实际上只保留synchronized块threadY()彼此相邻的允许情况:即情况 A、C 和 D。
由于此优化后没有出现新的可能执行,因此此优化是合法的。
对于更严格和详细的解释,我建议:
| 归档时间: |
|
| 查看次数: |
241 次 |
| 最近记录: |