多執行緒併發的3個特性

2022-09-04 21:06:16 字數 1794 閱讀 1471

多執行緒併發開發中,要知道什麼是多執行緒的原子性,可見性和有序性,以避免相關的問題產生。

2.1 原子性

原子性:即乙個操作或者多個操作 要麼全部執行並且執行的過程不會被任何因素打斷,要麼就都不執行

乙個很經典的例子就是銀行賬戶轉賬問題:

比如從賬戶a向賬戶b轉1000元,那麼必然包括2個操作:從賬戶a減去1000元,往賬戶b加上1000元。

試想一下,如果這2個操作不具備原子性,會造成什麼樣的後果。假如從賬戶a減去1000元之後,操作突然中止。這樣就會導致賬戶a雖然減去了1000元,但是賬戶b沒有收到這個轉過來的1000元。

所以這2個操作必須要具備原子性才能保證不出現一些意外的問題。

2.2 可見性

可見性:當多個執行緒訪問同乙個變數時,乙個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值

舉個簡單的例子,看下面這段**:

//執行緒1執行的**

int i = 0;

i = 10;

​//執行緒2執行的**

j = i;

當執行緒1執行int i = 0這句時,i的初始值0載入到記憶體中,然後再執行i = 10,那麼在記憶體中i的值變為10了。

如果當執行緒1執行到int i = 0這句時,此時執行緒2執行 j = i,它讀取i的值並載入到記憶體中,注意此時記憶體當中i的值是0,那麼就會使得j的值也為0,而不是10。

這就是可見性問題,執行緒1對變數i修改了之後,執行緒2沒有立即看到執行緒1修改的值。

2.3 有序性

有序性:程式執行的順序按照**的先後順序執行

int count = 0;

boolean flag = false;

count = 1; //語句1

flag = true; //語句2

以上**定義了乙個int型變數,定義了乙個boolean型別變數,然後分別對兩個變數進行賦值操作。從**順序上看,語句1是在語句2前面的,那麼jvm在真正執行這段**的時候會保證語句1一定會在語句2前面執行嗎?不一定,為什麼呢?這裡可能會發生指令重排序(instruction reorder)。

什麼是重排序?一般來說,處理器為了提高程式執行效率,可能會對輸入**進行優化,它不保證程式中各個語句的執行先後順序同**中的順序一致。

as-if-serial:無論如何重排序,程式最終執行結果和**順序執行的結果是一致的。j**a編譯器、執行時和處理器都會保證j**a在單執行緒下遵循as-if-serial語意)

上面的**中,語句1和語句2誰先執行對最終的程式結果並沒有影響,那麼就有可能在執行過程中,語句2先執行而語句1後執行。但是要注意,雖然處理器會對指令進行重排序,但是它會保證程式最終結果會和**順序執行結果相同,那麼它靠什麼保證的呢?

再看下面乙個例子:

int a = 10; //語句1

int b = 2; //語句2

a = a + 3; //語句3

b = a*a; //語句4

這段**有4個語句,那麼可能的乙個執行順序是: 語句2 語句1 語句3 語句4

不可能是這個執行順序: 語句2 語句1 語句4 語句3

因為處理器在進行重排序時是會考慮指令之間的資料依賴性,如果乙個指令instruction 2必須用到instruction 1的結果,那麼處理器會保證instruction 1會在instruction 2之前執行。雖然重排序不會影響單個執行緒內程式執行的結果,但是多執行緒會有影響

下面看乙個例子:

從上面可以看出,重排序不會影響單個執行緒的執行,但是會影響到執行緒併發執行的正確性。

要想併發程式正確地執行,必須要保證原子性、可見性以及有序性。只要有乙個沒有被保證,就有可能會導致程式執行不正確。

(多執行緒)多執行緒的併發安全

多執行緒併發操作同乙個資源 同步鎖 多執行緒操作的鎖必須唯一 必須搞清楚 哪些 需要同步?那些在操作共享資源的 只要包含非讀的操作,或者根據共享資源進行條件判斷的,就需要同步!同步 塊解決 package com.gc.thread 多執行緒操作共享資源 併發 執行緒安全問題 同步 鎖 相對而言效能...

多執行緒併發

多執行緒併發主要有3個方面 1 同步器 主要有synchronized,reentrantlock 訊號量,門栓 countdownlatch 障柵 cyclicbarrier 交換器。2 同步容器 主要包括 對映 集 佇列 對映 concurrenthashmap,concurrentskipli...

多執行緒併發

更簡單的執行緒池 多執行緒和多程序都可以很容易的實現併發,協程通過切換上下文來充分利用cpu實現併發效果 threading模組 thread類的基本狀態和行為 屬性名和值 name none,group none,target none,args kwargs daemon none 方法 sta...