Java 執行緒通訊的安全問題 同步

2021-08-14 09:59:15 字數 2579 閱讀 2748

執行緒間的通訊 :其實就是多個執行緒操作同一資源,但是操作的動作不同

注意:

1、多個執行緒

2、同一資源

3、操作動作不同

例如乙個場景:輸入執行緒(input) 和 輸出執行緒(output) ,輸入執行緒負責操作資源(resource),resource 有 name(string) 和 ***(string)兩個變數,輸入執行緒(input) 負責為 resource 的成員賦值,輸出執行緒 (output)列印值

分析 : 按照正常的場景來說,輸入執行緒(input)一旦為資源(resource)賦值完成後,輸出執行緒(output) 應該列印資源(resource)的成員變數值。同一資源,可通過建構函式將資源傳入執行緒。

先看如下**:

//資源

class

resource

//輸入執行緒

class

input

implements

runnable

public

void run()

else

// 目的在於做切換,賦值不同是為了更好區分是否存在問題

x = (x+1)%2;}}

}//輸出執行緒

class

output

implements

runnable

public

void run()

}}//主函式

public

class

threadwaitandnotify

}

看下列印結果(擷取部分):

輸出執行緒:傑克...man

輸出執行緒:jack...男

輸出執行緒:傑克...男

輸出執行緒:jack...man

輸出執行緒:傑克...男

輸出執行緒:傑克...man

分析: 從列印結果上來說,沒達到我們的要求,正常來說,應該是中文對應中文,英文對應英文輸出才對 ! 那為什麼會出現如下問題呢 ?其實,原因很簡單,假設輸入執行緒 (input)第一次 賦值 name = 「jack」,*** = 「man」,此時輸入執行緒(input)繼續享有執行權,做切換賦值,當賦值到 name = 「傑克」時,即將進行*** = 「男」賦值時,失去了執行權,此時,cpu執行權被輸出執行緒(output)拿到,輸出操作資源(res)的成員變數值,由於是操作同一資源,此時資源(res)的 name = 「傑克」, *** = 「man」,將其輸出。導致了如上結果

解決方案: 同步。那麼同步應該注意哪些地方呢 ?

( 1 ) 首先明白 執行緒 對資源的操作 ** 是哪些,這個比較好解決,就是 run方法的**。

( 2 ) 其次,鎖必須唯一。那有兩種選擇,可以是res物件,也可以是位元組碼檔案物件(在記憶體中,input.class和ouput.class也是唯一存在的)

修改**如下:

//資源

class

resource

//輸入執行緒

class

input

implements

runnable

public

void run()

else

x = (x+1)%2;}}

}}//輸出執行緒

class

output

implements

runnable

@override

public

void run() }}

}//主函式

public

class

threadwaitandnotify

}

列印結果(擷取部分):

輸出執行緒:jack...man

輸出執行緒:jack...man

輸出執行緒:jack...man

輸出執行緒:jack...man

輸出執行緒:傑克...男

輸出執行緒:傑克...男

輸出執行緒:傑克...男

執行緒安全問題是解決了,但是,跟我們預期的結果還是有些差距? 回到最初文章開頭我描述的場景,我們期望的結果是,輸入執行緒(input)順利對操作資源(res)賦值完成後,輸出執行緒(output)馬上能夠列印輸入執行緒的結果。

如下:

輸出執行緒:jack...man

輸出執行緒:傑克...男

輸出執行緒:jack...man

輸出執行緒:傑克...男

輸出執行緒:jack...man

輸出執行緒:傑克...男

輸出執行緒:jack...man..

.

為什麼我們解決了執行緒安全問題,但是沒達到我們想要的結果呢?

分析這個原因也很簡單 : 當輸入執行緒(input)操作資源(res)完成後,假設輸入執行緒(input)這時候失去執行權,而輸出執行緒(output)在短時間內得到了執行權,就會瘋狂列印這個結果。如何解決呢?這個涉及到乙個知識點,執行緒的等待喚醒機制。下篇博文介紹。

本篇博文相關**放這裡

java再複習 執行緒的安全問題以及同步

使用多執行緒,最重要的就是安全問題,何為安全問題?public class threadtest1 class myrunnable implements runnable catch interruptedexception e system.out.println i 執行結果 87 6543 ...

多執行緒安全問題 同步方法

2 同步方法 同步方法是指進入該方法時需要獲取this 物件的同步鎖,在方法上使用 synchronized 關鍵字,使用this 物件作為鎖,也就是使用了當前物件,因為鎖住了方法,所以相對於代 碼塊來說效率相對較低。注 靜態同步方法的鎖是該方法所在的類的位元組碼檔案物件,即類名.class 檔案 ...

Java學習筆記 執行緒安全問題

1 多執行緒的實現 1 繼承thread類 主函式中通過建立多個subthread類物件,並呼叫其start 方法。subthread類物件中屬性資料獨佔。2 實現runnable介面 主函式中建立乙個runnable介面實現類物件,同時建立多個thread類物件,並傳入介面物件,通過各thread...