1. 線程同步的幾種實現方法
java中多線程的實現方法有兩種:1.直接繼承thread類;2.實現runnable介面;同步的實現方法有五種:1.同步方法;2.同步代碼塊;3.使用特殊域變數(volatile)實現線程同步;4.使用重入鎖實現線程同步;5.使用局部變數實現線程同步 。
其中多線程實現過程中需注意重寫或者覆蓋run()方法,而對於同步的實現方法中使用較常使用的是利用synchronized編寫同步方法和代碼塊。
2. 線程同步的幾種方法的總結
線程同步的方式包括:互斥鎖、讀寫鎖、條件變數、信號量和令牌。互斥鎖和讀寫鎖:提供對臨界資源的保護,當多線程試圖訪問臨界資源時,都必須通過獲取鎖的方式來訪問臨界資源。(臨界資源:是被多線程共享的資源)當讀寫線程獲取鎖的頻率差別不大時,一般採用互斥鎖,如果讀線程訪問臨界資源的頻率大於寫線程,這個時候採用讀寫鎖較為合適,讀寫鎖允許多個讀線程同時訪問臨界資源,讀寫線程必須互斥訪問臨界資源。讀寫鎖的實現採用了互斥鎖,所以在讀寫次數差不多的情況下採用讀寫鎖性能沒有直接採用互斥鎖來的高。條件變數:提供線程之間的一種通知機制,當某一條件滿足時,線程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上的線程,資源被釋放,你可以使用資源了。
3. Java 線程同步幾種方式
(1)同步方法:
即有synchronized關鍵字修飾的方法。 由於java的每個對象都有一個內置鎖,當用此關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處於阻塞狀態。
(2)同步代碼塊
即有synchronized關鍵字修飾的語句塊。被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步
(3)使用特殊域變數(Volatile)實現線程同步
a.volatile關鍵字為域變數的訪問提供了一種免鎖機制
b.使用volatile修飾域相當於告訴虛擬機該域可能會被其他線程更新
c.因此每次使用該域就要重新計算,而不是使用寄存器中的值
d.volatile不會提供任何原子操作,它也不能用來修飾final類型的變數
(4)使用重入鎖實現線程同步
在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現了Lock介面的鎖, 它與使用synchronized方法和快具有相同的基本行為和語義,並且擴展了其能力。
(5)使用局部變數實現線程同步
4. 多線程同步方式有哪些
java中多線程的實現方法有兩種:
1.直接繼承thread類;
2.實現runnable介面同步的實現方法有五種:1.同步方法;2.同步代碼塊;3.使用特殊域變數(volatile)實現線程同步;4.使用重入鎖實現線程同步;5.使用局部變數實現線程同步
5. 為什麼要線程同步,說出線程同步的幾種方法
線程有時候回和其他線程共享一些資源,比如內存、資料庫等。當多個線程同時讀寫同一份共享資源的時候,可能會發生沖突。這時候,我們就需要引入線程「同步」機制,即各位線程之間要有順序使用,不能雜亂無章隨意使用。
線程同步的方法
1、wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。
(5)線程同步的方法有哪些擴展閱讀:
在一般情況下,創建一個線程是不能提高程序的執行效率的,所以要創建多個線程。但是多個線程同時運行的時候可能調用線程函數,在多個線程同時對同一個內存地址進行寫入,由於CPU時間調度上的問題,寫入數據會被多次的覆蓋,所以就要使線程同步。
在多線程編程裡面,一些敏感數據不允許被多個線程同時訪問,此時就使用同步訪問技術,保證數據在任何時刻,最多有一個線程訪問,以保證數據的完整性。
6. 線程同步有幾種實現方法,都是什麼
實現線程有兩種繼承thread類或者實現runnable介面...實現同步也有兩種,一種是用同步方法,一種是用同步塊..同步方法就是在方法返回類型後面加上synchronized,比如:
publicvoidsynchronizedadd(){...}
同步塊就是直接寫:synchronized(這里寫需要同步的對象){...}
7. java 實現線程同步的方式有哪些
實現同步機制有兩個方法:
1、同步代碼塊:
synchronized(同一個數據){} 同一個數據:就是N條線程同時訪問一個數據。
2、同步方法:
public synchronized 數據返回類型 方法名(){}
就是使用 synchronized 來修飾某個方法,則該方法稱為同步方法。對於同步方法而言,無需顯示指定同步監視器,同步方法的同步監視器是 this 也就是該對象的本身(這里指的對象本身有點含糊,其實就是調用該同步方法的對象)通過使用同步方法,可非常方便的將某類變成線程安全的類,具有如下特徵:
1,該類的對象可以被多個線程安全的訪問。
2,每個線程調用該對象的任意方法之後,都將得到正確的結果。
3,每個線程調用該對象的任意方法之後,該對象狀態依然保持合理狀態。
註:synchronized關鍵字可以修飾方法,也可以修飾代碼塊,但不能修飾構造器,屬性等。
實現同步機制注意以下幾點: 安全性高,性能低,在多線程用。性能高,安全性低,在單線程用。
1,不要對線程安全類的所有方法都進行同步,只對那些會改變共享資源方法的進行同步。
2,如果可變類有兩種運行環境,當線程環境和多線程環境則應該為該可變類提供兩種版本:線程安全版本和線程不安全版本(沒有同步方法和同步塊)。在單線程中環境中,使用線程不安全版本以保證性能,在多線程中使用線程安全版本.
8. 線程同步幾種方式
進程中線程同步的四種常用方式:
1、 臨界區(CCriticalSection)
當多個線程訪問一個獨占性共享資源時,可以使用臨界區對象。擁有臨界區的線程可以訪問被保護起來的資源或代碼段,其他線程若想訪問,則被掛起,直到擁有臨界區的線程放棄臨界區為止。具體應用方式:
1、 定義臨界區對象CcriticalSection g_CriticalSection;
2、 在訪問共享資源(代碼或變數)之前,先獲得臨界區對象,g_CriticalSection.Lock();
3、 訪問共享資源後,則放棄臨界區對象,g_CriticalSection.Unlock();
2、 事件(CEvent)
事件機制,則允許一個線程在處理完一個任務後,主動喚醒另外一個線程執行任務。比如在某些網路應用程序中,一個線程如A負責偵聽通信埠,另外一個線程B負責更新用戶數據,利用事件機制,則線程A可以通知線程B何時更新用戶數據。每個Cevent對象可以有兩種狀態:有信號狀態和無信號狀態。Cevent類對象有兩種類型:人工事件和自動事件。
自動事件對象,在被至少一個線程釋放後自動返回到無信號狀態;
人工事件對象,獲得信號後,釋放可利用線程,但直到調用成員函數ReSet()才將其設置為無信號狀態。在創建Cevent對象時,默認創建的是自動事件。
1、1234CEvent(BOOL bInitiallyOwn=FALSE, BOOL bManualReset=FALSE, LPCTSTR lpszName=NULL, LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);
bInitiallyOwn:指定事件對象初始化狀態,TRUE為有信號,FALSE為無信號;
bManualReset:指定要創建的事件是屬於人工事件還是自動事件。TRUE為人工事件,FALSE為自動事件;
後兩個參數一般設為NULL,在此不作過多說明。
2、BOOL CEvent::SetEvent();
將Cevent類對象的狀態設置為有信號狀態。如果事件是人工事件,則Cevent類對象保持為有信號狀態,直到調用成員函數ResetEvent()將其重新設為無信號狀態時為止。如果為自動事件,則在SetEvent()後將事件設置為有信號狀態,由系統自動重置為無信號狀態。
3、BOOL CEvent::ResetEvent();
將事件的狀態設置為無信號狀態,並保持該狀態直至SetEvent()被調用為止。由於自動事件是由系統自動重置,故自動事件不需要調用該函數。
一般通過調用WaitForSingleObject()函數來監視事件狀態。
3、 互斥量(CMutex)
互斥對象和臨界區對象非常相似,只是其允許在進程間使用,而臨界區只限制與同一進程的各個線程之間使用,
但是更節省資源,更有效率。
4、 信號量(CSemphore)
當需要一個計數器來限制可以使用某共享資源的線程數目時,可以使用「信號量」對象。CSemaphore類對象保存了對當前訪問某一個指定資源的線程的計數值,該計數值是當前還可以使用該資源的線程數目。如果這個計數達到了零,則所有對這個CSemaphore類對象所控制的資源的訪問嘗試都被放入到一個隊列中等待,直到超時或計數值不為零為止。
CSemaphore(
LONG lInitialCount = 1,
LONG lMaxCount = 1,
LPCTSTR pstrName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttributes = NULL
);
lInitialCount:信號量對象的初始計數值,即可訪問線程數目的初始值;
lMaxCount:信號量對象計數值的最大值,該參數決定了同一時刻可訪問由信號量保護的資源的線程最大數目;
後兩個參數在同一進程中使用一般為NULL,不作過多討論;
一般是將當前可用資源計數設置為最大資源計數,每增加一個線程對共享資源的訪問,當前可用資源計數就減1,只要當前可用資源計數大於0,就可以發出信號量信號。如果為0,則放入一個隊列中等待。線程在處理完共享資源後,應在離開的同時通過ReleaseSemaphore()函數將當前可用資源數加1。
9. 線程同步有幾種方法
wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先順序。
Allnotity():喚醒所有處入等待狀態的線程,注意並不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
10. 線程同步的方法都有什麼
同步的實現方面有兩種,分別是synchronized,wait與notify wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先順序。
Allnotity():喚醒所有處入等待狀態的線程。