1. 程式人生 > >一個多線程問題的邏輯思考

一個多線程問題的邏輯思考

llb 但是 理解 cal logs 兩個 才會 進行 col

同事給了一段代碼,用來實現開始錄制聲音和停止錄制,偽代碼如下:

 1 void StartRecord()
 2 {
 3   new Thread()
 4   {
 5     void run()
 6     {
 7       m_isRecording = true;
 8       Java_StartRecord();
 9       while(m_isRecording == true)
10       {
11         Java_RecordCallback();
12       }
13     }
14   }
15 }
16 
17 void EndRecord()
18 { 19   m_isRecording = false; 20 }

StartRecord函數開啟錄制線程,通過m_isRecording 來設置錄制狀態。

初一看這裏沒什麽問題,並且大多數情況下也確實可以正常工作。但是對於特殊的情況,比如StartRecord之後很快調用EndRecord,這時候StartRecord創建了錄制線程,但是錄制線程還沒有開始執行。由於線程調度的不確定性,EndReocord確實存在在錄制線程前執行的情況。這種情況下,EndRecord把m_isRecording 設置為了false,而錄制線程在執行的時候又把m_isRecording 設置成了true,這就回導致錄制線程永遠不會結束。解決這個問題的辦法是改成下面的代碼:

 1 void StartRecord()
 2 {
 3    m_isRecording = true;
 4     new Thread()
 5     {
 6       void run()
 7       {
 8        Java_StartRecord();
 9        while(m_isRecording == true)
10        {
11          Java_RecordCallback();
12        }
13      }
14    }
15 }
16  
17 void EndRecord()
18 {
19    m_isRecording = false
; 20 }

這樣雖然解決了問題,但也應該進行更深入的思考。其關鍵就在於m_isRecording的意義。這裏涉及到了兩個客體,一個是主線程(調用StartRecord和EndRecord的線程),另外一個是錄制線程。在第一段代碼中,EndRecord函數中認為m_isRecording標識主線程的狀態,因為只有主線程才會調用EndRecord函數病修改m_isRecording的值。但是在StartRecord函數中卻是錄制線程修改了m_isRecording的值,同時又在錄制線程中讀取m_isRecording。錄制線程認為m_isRecording表示的是錄制線程的狀態。所以在第一段代碼中,對m_isRecording的理解是存在歧義的。而第二段代碼就非常明確。

暫時理解到這個層次,以後有了更深的理解再記下來。

一個多線程問題的邏輯思考