如何實現線程同步?
線程同步有幾種實現方法,都是什麼?
答:多線程有兩種實現方法,分別是繼承Thread類與實現Runnable接口
同步的實現方面有兩種,分別是synchronized,wait與notify
線程同步的幾種方法的總結
線程同步的方式包括:互斥鎖、讀寫鎖、條件變量、信號量和令牌。互斥鎖和讀寫鎖:提供對臨界資源的保護,當多線程試圖訪問臨界資源時,都必須通過獲取鎖的方式來訪問臨界資源。(臨界資源:是被多線程共享的資源)當讀寫線程獲取鎖的頻率差別不大時,一般採用互斥鎖,如果讀線程訪問臨界資源的頻率大於寫線程,這個時候採用讀寫鎖較為合適,讀寫鎖允許多個讀線程同時訪問臨界資源,讀寫線程必須互斥訪問臨界資源。讀寫鎖的實現採用了互斥鎖,所以在讀寫次數差不多的情況下采用讀寫鎖性能沒有直接採用互斥鎖來的高。條件變量:提供線程之間的一種通知機制,當某一條件滿足時,線程A可以通知阻塞在條件變量上的線程B,B所期望的條件已經滿足,可以解除在條件變量上的阻塞操作,繼續做其他事情。信號量:提供對臨界資源的安全分配。如果存在多份臨界資源,在多個線程爭搶臨界資源的情況下,向線程提供安全分配臨界資源的方法。如果臨界資源的數量為1,將退化為鎖。令牌:一種高級的線程同步的方法。它既提供鎖的安全訪問臨界資源的功能,又利用了條件變量使得線程爭奪臨界資源時是有序的。下面提供Token在ACE中的一種實現方法。可以從下面的類圖,可以看到ACE是如何設計Token的。 ACE_Token:這個類是Token類,提供了獲取和釋放Token的方法。對於Token的獲取策略,ACE提供兩種實現:FIFO和LIFO。Token中對應著兩個隊列,一個是獲取Token是為了寫的隊列,另外一個是獲取Token是為了讀的隊列。ACE_Token_Queue:隊列是一個鏈表,該類提供對鏈表的管理操作。ACE_Token_Entry:是隊列中存放的元素,提供了對條件變量的封裝,一個元素代表一個線程試圖獲取Token。如果Token已經被獲取,線程需要阻塞在自己的Token上(隊列Entry中的條件變量上)。等待Token持有者釋放該Token,並通知阻塞的線程。 下面對ACE_Token中的組要方法提供分析。 獲取判斷是否有線程已經持有互斥鎖了,如果沒人持有,表示臨界資源是可用的,那麼可以立即返回成功。檢查是不是線程嘗試遞歸獲取互斥鎖。因為Token支持這種情況,所以也可立即返回成功。同時將nesting計數器自增。創建一個Token Entry,並將其排入隊列。調用用戶自定義的Hook方法,在線程進行sleep之前,用戶可以調用自定義的Hook方法。線程睡眠,如果線程喚醒後,發現當前線程不是Token的擁有者將繼續睡眠。線程被喚醒後,將Token entry從隊列中刪除。釋放如果發現嵌套層數大於0,需要將嵌套層數的計數器減一,然後讓該線程繼續持有Token。否則,該線程負責從隊列中按照一定的策略,取出Token entry,並通過該Entry通知阻塞在Entry上的線程,資源被釋放,你可以使用資源了。
請用技術語言介紹下線程同步,併發操作怎麼控制
現在流行的進程線程同步互斥的控制機制,其實是由最原始最基本的4種方法實現的。由這4種方法組合優化就有了.Net和Java下靈活多變的,編程簡便的線程進程控制手段。
這4種方法具體定義如下 在《操作系統教程》ISBN 7-5053-6193-7 一書中可以找到更加詳細的解釋
1、臨界區:通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。
2、互斥量:為協調共同對一個共享資源的單獨訪問而設計的。
3、信號量:為控制一個具有有限數量用戶資源而設計。
4、事 件:用來通知線程有一些事件已發生,從而啟動後繼任務的開始。
臨界區(Critical Section)
保證在某一時刻只有一個線程能訪問數據的簡便辦法。在任意時刻只允許一個線程對共享資源進行訪問。如果有多個線程試圖同時訪問臨界區,那麼在有一個線程進入後其他所有試圖訪問此臨界區的線程將被掛起,並一直持續到進入臨界區的線程離開。臨界區在被釋放後,其他線程可以繼續搶佔,並以此達到用原子方式操作共享資源的目的。
臨界區包含兩個操作原語:
EnterCriticalSection() 進入臨界區
LeaveCriticalSection() 離開臨界區
EnterCriticalSection()語句執行後代碼將進入臨界區以後無論發生什麼,必須確保與之匹配的LeaveCriticalSection()都能夠被執行到。否則臨界區保護的共享資源將永遠不會被釋放。雖然臨界區同步速度很快,但卻只能用來同步本進程內的線程,而不可用來同步多個進程中的線程。
MFC提供了很多功能完備的類,我用MFC實現了臨界區。MFC為臨界區提供有一個CCriticalSection類,使用該類進行線程同步處理是非常簡單的。只需在線程函數中用CCriticalSection類成員函數Lock()和UnLock()標定出被保護代碼片段即可。Lock()後代碼用到的資源自動被視為臨界區內的資源被保護。UnLock後別的線程才能訪問這些資源。
//CriticalSection
CCriticalSection global_CriticalSection;
// 共享資源
char global_Array[256];
//初始化共享資源
void InitializeArray()
{
for(int i = 0;i<256;i++)
{
global_Array[i]=I;
}
}
//寫線程
UINT Global_ThreadWrite(LPVOID pParam)
{
CEdit *ptr=(CEdit *)pParam;
ptr->SetWindowText("");
//進入臨界區
global_CriticalSection.Lock();
for(int i = 0;i<256;i++)
{
global_Array[i]=W;
ptr->SetWindowText(global_Array);
Sleep(10);
}
//離開臨界區
global_CriticalSection.Unlock();
return 0;
}
//刪除線程
UINT Global_ThreadDelete(LPVOID pParam)
{
CEdit *ptr=(CE......
C語言怎麼實現多線程同步
使用pthread庫執行多線程,這個是Linux下的線程庫 Windows下應該有自己的API,不過這種東西一般還是以Linux為標準。pthread_create()創建一個線程,傳入fun()的函數指針就行了。
然後這個Beep()的需求要進行線程間通信,可以用共享內存的方法,設一個bool變量flag共享,然後beep的時候設為false,beep完設成true。fun()裡面每次看一下這個flag,是false的話就不做動作等下一秒,基本可以滿足需求。
這樣做的好處是實現簡單,但時間是以1s為單位的。如果要8秒結束立刻執行,需要用條件變量的方法來控制,比較複雜,這樣的實現方式一個可以滿足需求了。
Java線程同步的方法
等待喚醒機制
wait():讓線程等待。將線程存儲到一個線程池中。
notify():喚醒被等待的線程。通常都喚醒線程池中的第一個。讓被喚醒的線程處於臨時阻塞狀態。
notifyAll(): 喚醒所有的等待線程。將線程池中的所有線程都喚醒,讓它們從凍結狀體轉到臨時阻塞狀態.
這三個方法用於操作線程,可是定義在了Object類中,為什麼呢?
因為,這三個方法在使用時,都需要定義在同步中,要明確這些方法所操作的線程所屬於鎖。
簡單說。在A鎖被wait的線程,只能被A鎖的notify方法喚醒。
所以必須要表示wait notify方法所屬的鎖對象,而鎖對象可以是任意的對象。
可以被任意的對象調用的方法肯定弧義在Object類中。
注意:等待喚醒機制,通常都用在同步中,因為需要鎖的支持。
而且必須要明確wait notify 所作用的鎖對象。
JDK1.5後的鎖
在jdk1.5版本之後,
出現了一些新的特性,將原理的線程進行了改良。
在java.util.concurrent.locks包中提供了一個接口Lock。替代了synchronized。
synchronized。使用的是鎖操作是隱式的。
Lock接口,使用的鎖操作是顯示的。
由兩個方法來完成:
lock():獲取鎖。
unlock():釋放鎖。
還有一個對象,Condition.
該對象的出現替代了Object中的wait notify notifyAll這些操作監視器的方法。
替代後的方式:await signal signalAll.
線程同步互斥的4種方式
臨界區(Critical Section)、互斥量(Mutex)、信號量(Semaphore)、事件(Event)的區別
1、臨界區:通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。在任意時刻只允許一個線程對共享資源進行訪問,如果有多個線程試圖訪問公共資源,那麼在有一個線程進入後,其他試圖訪問公共資源的線程將被掛起,並一直等到進入臨界區的線程離開,臨界區在被釋放後,其他線程才可以搶佔。
2、互斥量:採用互斥對象機制。 只有擁有互斥對象的線程才有訪問公共資源的權限,因為互斥對象只有一個,所以能保證公共資源不會同時被多個線程訪問。互斥不僅能實現同一應用程序的公共資源安全共享,還能實現不同應用程序的公共資源安全共享
3、信號量:它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目
4、事 件: 通過通知操作的方式來保持線程的同步,還可以方便實現對多個線程的優先級比較的操作
如何實現序列化?如何實現線程的同步
在java5以前實現多線程有兩種方法(繼承Thread類和實現Runnable接口)
它們分別為:
使用new Thread()和new Thread(Runnable)形式
第一種直接調用thread的run方法,所以,往往使用Thread子類,即new SubThread()。
第二種調用
Runnable的run方法。
第一種:
new Thread(){}.start();這表示調用Thread子類對象的run方法,new Thread(){}表示一個Thread的匿名子類的實例對象,子類加上run方法後的代碼如下:
new Thread(){
public void run(){
}
}.start();
第二種:
new Thread(
new Runnable(){}
).start();
這表示調用Thread對象接受的Runnable對象的run方法,new Runnable(){}表示一個Runnable的匿名子類的實例對象,
runnable的子類加上run方法後的代碼如下:
new Thread(new Runnable(){
public void run(){
}
}
).start();
線程同步有幾種實現方法,都是什麼
繼承Thread 類與實現Runnable 接口都能實現多線程
synchronized,wait 與notify 可以實現同步
實現線程同步的話在java中可以怎麼實現
用synchronize關鍵字,可以有代碼段加鎖,對象加鎖,方法加鎖等方法實現線程同步