java多线程并行执行命令_深入理解Java多线程与并发框(第④篇)——重排序、屏障指令、as-if-serial规则...

# 一、重排序
前篇文章已經(jīng)講了Java內(nèi)存模型和與其三個特性:原子性、可見性、有序性。但事實(shí)上,為了提升程序的執(zhí)行性能,編譯器 和 處理器 常常會對程序指令序列進(jìn)行 重排序。
重排序分為以下幾種:
- 編譯器優(yōu)化重排序
- 處理器重排序
- 指令級并行重排序
- 內(nèi)存系統(tǒng)重排序
# 二、屏障指令
fence
內(nèi)存屏障(Memory Barrier,或稱為內(nèi)存柵欄,Memory Fence)是一種CPU指令,用于控制特定條件下的重排序和內(nèi)存可見性問題。Java編譯器也會根據(jù)內(nèi)存屏障的規(guī)則在一定程度地禁止重排序。
# 三、as-if-serial 語句
>重排序也不能毫無規(guī)則,否則語義就變得不可讀, as-if-serial語句 給重排序戴上緊箍咒,起到約束作用。
**as-if-serial語句**規(guī)定重排序要滿足以下兩個規(guī)則:
- 在單線程環(huán)境下不能改變程序執(zhí)行的結(jié)果;
- 存在數(shù)據(jù)依賴關(guān)系代碼(指令)片段的不允許重排序。
比如下面的代碼:
```
int a = 1;
// ①
int b = 2;
// ②
int c = a + b;
// 依賴于 ① 和 ②
return c;
```
可能會被優(yōu)化成:
```
int b = 2;
// ②
int a = 1;
// ①
int c = a + b;
// 依賴于 ① 和 ②
return c;
```
上述的重排序既沒有改變單線程下程序運(yùn)行的結(jié)果,又沒有對存在依賴關(guān)系的指令進(jìn)行重排序。
# 四、happens-before 規(guī)則
產(chǎn)生的背景是為了確保多線程操作下具有內(nèi)存可見性。
如果一個操作執(zhí)行的結(jié)果需要對另一個操作可見,那么這兩個操作之間必須要存在happens-before關(guān)系。換句話說,操作1 happens-before 操作2,那么操作1的結(jié)果是對操作2可見的。
這里提到的兩個操作既可以是在一個線程之內(nèi),也可以是在不同線程之間。
**規(guī)則**:
1. 程序順序規(guī)則:一個線程中的每個操作,happens-before 于該線程中的任意后續(xù)操作
2. 監(jiān)視器鎖規(guī)則:對一個鎖的解鎖,happens-before 于隨后對這個鎖的加鎖
3. volatile變量規(guī)則:對一個volatile域的寫,happens-before 于任意后續(xù)對這個volatile域的讀
4. 傳遞性:如果A happens-before B,且B happens-before C,那么A happens-before C
5. start規(guī)則:如果線程A執(zhí)行操作ThreadB.start()(啟動線程B),那么A線程的ThreadB.start()操作happens-before于線程B中的任意操作
6. join規(guī)則:如果線程A執(zhí)行操作ThreadB.join()并成功返回,那么線程B中的任意操作happens-before于線程A從ThreadB.join()操作成功返回。
# 總結(jié):
as-if-serial 語句保證單線程環(huán)境下不能改變程序執(zhí)行的結(jié)果,happens-before 規(guī)則保證多線程環(huán)境下不能改變程序執(zhí)行的結(jié)果。
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/69964492/viewspace-2682230/,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任。
總結(jié)
以上是生活随笔為你收集整理的java多线程并行执行命令_深入理解Java多线程与并发框(第④篇)——重排序、屏障指令、as-if-serial规则...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php pdo mysql 乱码,php
- 下一篇: python的def语句_【零基础学Py