1. 程式人生 > >執行緒同步常用方式與區別

執行緒同步常用方式與區別

在介紹執行緒同步/互斥之前,我們先要理解同步與互斥的概念,引用書上的解釋來說明這2個概念:
1、執行緒(程序)同步的主要任務
在引入多執行緒後,由於執行緒執行的非同步性,會給系統造成混亂,特別是在急用臨界資源時,如多個執行緒急用同一臺印表機,會使列印結果交織在一起,難於區分。當多個執行緒急用共享變數,表格,連結串列時,可能會導致資料處理出錯,因此執行緒同步的主要任務是使併發執行的各執行緒之間能夠有效的共享資源和相互合作,從而使程式的執行具有可再現性。
2、執行緒(程序)之間的制約關係?
當執行緒併發執行時,由於資源共享和執行緒協作,使用執行緒之間會存在以下兩種制約關係。
(1)間接相互制約。一個系統中的多個執行緒必然要共享某種系統資源,如共享CPU,共享I/O裝置,所謂間接相互制約即源於這種資源共享,印表機就是最好的例子,執行緒A在使用印表機時,其它執行緒都要等待。
(2)直接相互制約。這種制約主要是因為執行緒之間的合作,如有執行緒A將計算結果提供給執行緒B作進一步處理,那麼執行緒B線上程A將資料送達之前都將處於阻塞狀態。
歸納如下:
1、互斥是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
2、同步是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。
3、同步其實已經實現了互斥,所以同步是一種更為複雜的互斥。
4、互斥是一種特殊的同步。
間接相互制約可以稱為互斥,直接相互制約可以稱為同步

,對於互斥可以這樣理解,執行緒A和執行緒B互斥訪問某個資源則它們之間就會產個順序問題——要麼執行緒A等待執行緒B操作完畢,要麼執行緒B等待執行緒操作完畢,這其實就是執行緒的同步了。因此同步包括互斥,互斥其實是一種特殊的同步。

下面來看看執行緒同步的5種常用方式:
1、 臨界資源(CCriticalSection)/關鍵段
當多個執行緒訪問一個獨佔性共享資源時,可以使用臨界區物件。擁有臨界區的執行緒可以訪問被保護起來的資源或程式碼段,其他執行緒若想訪問,則被掛起,直到擁有臨界區的執行緒放棄臨界區為止。(臨界區只能同一程序中執行緒使用,不能跨程序使用)
臨界資源:同時只允許一個程序使用的資源。
臨界區:程序中用於訪問臨界資源的程式碼段,又稱臨界段。
每個程序的臨界區程式碼可以不同,臨界區程式碼由於要訪問臨界資源,因此要在進入臨界區之前進行檢查,至於每個程序對臨界資源進行怎樣的操作,這和臨界資源及互斥同步管理是無關的。
使用方式:
1.定義臨界區物件
CcriticalSection g_CriticalSection;


2.在訪問共享資源(程式碼或變數)之前,先獲得臨界區物件
g_CriticalSection.Lock();
3.訪問共享資源後,則放棄臨界區物件
g_CriticalSection.Unlock();
臨界區一般使用鎖的方式來實現,常見的互斥鎖和讀寫鎖:提供對臨界資源的保護,當多執行緒試圖訪問臨界資源時,都必須通過獲取鎖的方式來訪問臨界資源。(臨界資源:是被多執行緒共享的資源)當讀寫執行緒獲取鎖的頻率差別不大時,一般採用互斥鎖,如果讀執行緒訪問臨界資源的頻率大於寫執行緒,這個時候採用讀寫鎖較為合適,讀寫鎖允許多個讀執行緒同時訪問臨界資源,讀寫執行緒必須互斥訪問臨界資源。讀寫鎖的實現採用了互斥鎖,所以在讀寫次數差不多的情況下采用讀寫鎖效能沒有直接採用互斥鎖來的高。
最後總結下關鍵段:
1.關鍵段共初始化化、銷燬、進入和離開關鍵區域四個函式。
2.關鍵段可以解決執行緒的互斥問題,但因為具有“執行緒所有權”,所以無法解決同步問題。
3.推薦關鍵段與旋轉鎖/自旋鎖配合使用。關於鎖,見本文後面

(注意:下面說的3種同步手段,事件,互斥量,訊號量都是核心物件,都可以跨程序使用)

2、 互斥量/互斥鎖(CMutex)
互斥量多用於多程序之間的執行緒互斥,用來確保一個執行緒獨佔一個資源的訪問。而且能正確處理資源遺棄的問題(“遺棄”問題就是——佔有某種資源的程序意外終止後,其它等待該資源的程序能否感知。,而事件與訊號量都無法處理遺棄問題,更多關於遺棄問題的分析,參考此處
互斥物件和臨界區物件非常相似,只是其允許在程序間使用,而臨界區只限制與同一程序的各個執行緒之間使用,但是更節省資源,更有效率。
相關函式:

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_destroy(pthread_mutex *mutex);
int pthread_mutex_unlock(pthread_mutex *

3、 事件(CEvent)/條件變數
事件機制,則允許一個執行緒在處理完一個任務後,主動喚醒另外一個執行緒執行任務。或者按照條件變數的說法,提供執行緒之間的一種通知機制。
每個Cevent物件可以有兩種狀態:有訊號狀態和無訊號狀態。
Cevent類物件有兩種型別:人工事件和自動事件。
相關函式:

int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);     
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);  
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);  //解除所有執行緒的阻塞

4、 訊號量(CSemphore)
當需要一個計數器來限制可以使用某共享資源的執行緒數目時,可以使用“訊號量”物件。
訊號量提供對臨界資源的安全分配。如果存在多份臨界資源,在多個執行緒爭搶臨界資源的情況下,向執行緒提供安全分配臨界資源的方法。如果臨界資源的數量為1,將退化為鎖。
IPC方式中也有訊號量,常常配合ipc共享記憶體來使用,作為程序之間以及同一程序不同執行緒間的同步手段。
使用方式:
CSemaphore類物件儲存了對當前訪問某一個指定資源的執行緒的計數值,該計數值是當前還可以使用該資源的執行緒數目。如果這個計數達到了零,則所有對這個CSemaphore類物件所控制的資源的訪問嘗試都被放入到一個佇列中等待,直到超時或計數值不為零為止。
執行緒在處理完共享資源後,應在離開的同時通過ReleaseSemaphore()函式將當前可用資源數加1。
相關函式:
訊號量函式的名字都以”sem_”打頭。執行緒使用的基本訊號量函式有四個。

#include <semaphore.h>
int sem_init (sem_t *sem , int pshared, unsigned int value);

這是對由sem指定的訊號量進行初始化,設定好它的共享選項(linux 只支援為0,即表示它是當前程序的區域性訊號量),然後給它一個初始值VALUE。

兩個原子操作函式:

int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);

這兩個函式都要用一個由sem_init呼叫初始化的訊號量物件的指標做引數。
sem_post:給訊號量的值加1;
sem_wait:給訊號量減1;對一個值為0的訊號量呼叫sem_wait,這個函式將會等待直到有其它執行緒使它不再是0為止。
int sem_destroy(sem_t *sem);
這個函式的作用是再我們用完訊號量後都它進行清理。歸還自己佔有的一切資源。
5、令牌:
一種高階的執行緒同步的方法。它既提供鎖的安全訪問臨界資源的功能,又利用了條件變數使得執行緒爭奪臨界資源時是有序的。

注意:
1、臨界區和互斥量都有“執行緒所有權”的概念,所以它們是不能用來實現執行緒間的同步的,只能用來實現互斥。
2、事件和訊號量都可以實現執行緒和程序間的互斥和同步。但是事件和訊號量都無法解決遺棄問題。
3、臨界區的效率是最高的,因為它不是核心物件。但是臨界區不能跨程序使用。
事件,互斥量,訊號量都是核心物件,可以跨程序使用,但相應的效率也會低很多。

相關推薦

執行同步常用方式區別

在介紹執行緒同步/互斥之前,我們先要理解同步與互斥的概念,引用書上的解釋來說明這2個概念: 1、執行緒(程序)同步的主要任務 在引入多執行緒後,由於執行緒執行的非同步性,會給系統造成混亂,特別是在急用臨界資源時,如多個執行緒急用同一臺印表機,會使列印結果交織

執行同步中sleepwait區別

1、函式 wait是Object的一個函式,指執行緒處於進入等待狀態,此時執行緒不佔用任何資源,不增加時間限制。wait可以被notify和notifyAll函式喚醒(這兩個也是Object的函

Java執行-同步和非同步的區別

1.                                         &nb

程序/執行同步方式和機制,程序間通訊【轉】

(轉自:https://www.cnblogs.com/virusolf/p/5331946.html) 一、程序/執行緒間同步機制。 臨界區、互斥區、事件、訊號量四種方式臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別

Java多執行2.9.實現執行常用方式-匿名內部類

實現執行緒的常用方式-匿名內部類 1、匿名內部類的格式 匿名內部類的格式。 本質:是該類或者介面的子類物件。 new 類名或者介面名() { 重寫方法; }; 2、實現執行緒的常用

並行流parallel,CompletableFutureExecutors執行池的使用區別

list並行操作在專案開發可以極大提高程式碼效率與效能,java8對其進行了很好的封裝,簡單使用研究一下: 1. 先自己建立一個list: // list在實際使用中要注意執行緒安全,Collections.synchronizedList寫操作效能高,Co

Java --- 執行同步和非同步的區別

1. Java 執行緒 同步與非同步 多執行緒併發時,多個執行緒同時請求同一個資源,必然導致此資源的資料不安全,A執行緒修改了B執行緒的處理的資料,而B執行緒又修改了A執行緒處理的數理。顯然這是由於全域性資源造成的,有時為了解決此問題,優先考慮使用區域性變數,

執行同步方式,有哪幾種】

【1】同步程式碼方法 sychronized 關鍵字修飾的方法 【2】同步程式碼塊 sychronized 關鍵字修飾的程式碼塊 【3】使用特殊變數域volatile實現執行緒同步 volat

執行同步--協同方式和互斥方式

參考部落格:http://www.cnblogs.com/kennyMc/archive/2012/12/15/2818887.html    參考部落格:http://www.cnblogs.com/xilentz/archive/2012/11/13/2767317.h

執行池的種類區別

在什麼情況下使用執行緒池? 1.單個任務處理的時間比較短 2.將需處理的任務的數量大 使用執行緒池的好處: 1.減少在建立和銷燬執行緒上所花的時間以及系統資源的開銷 2.如不使用執行緒池,有可能造成系統建立大量執行緒而導致消耗完系統記憶體以及

開始一個執行兩種方式區別

java 開始一個現成有兩中方法 :一是直接呼叫Thread例項的start()方法,二是將Runable例項傳給一個Thread例項然後呼叫它的start()方法。 首先讓我們看看Thread類的start() 方法: public synchronized void st

Java 多執行同步 鎖機制synchronized

要是很多人在等這把鑰匙,等鑰匙還回來以後,誰會優先得到鑰匙?Not guaranteed。象前面例子裡那個想連續使用兩個上鎖房間的傢伙,他中間還鑰匙的時候如果還有其他人在等鑰匙,那麼沒有任何保證這傢伙能再次拿到。 (JAVA規範在很多地方都明確說明不保證,象Thread.sleep()休息後多久會返回執行,相

Java執行同步方式有哪些?

1同步方法,有synchronized關鍵字修飾的方法   2同步程式碼塊 有synchronized 關鍵字修飾的

程序執行區別聯絡、程序執行的通訊方式.md

一、為什麼引入程序? 程序是為了提高CPU的執行效率,減少因為程式等待帶來的CPU空轉以及其他計算機軟硬體資源的浪費而提出來的。 二、為什麼引入執行緒? 為了減少程序切換和建立的開銷,提高執行效率和節省

執行池大小設定,CPU的核心數、執行數的關係和區別同步堵塞完全是兩碼事

執行緒池應該設定多少執行緒合適,怎麼樣估算出來。最近接觸到一些相關資料,現作如下總結。 最開始接觸執行緒池的時候,沒有想到就僅僅是設定一個執行緒池的大小居然還有這麼多的學問,汗顏啊。 首先,需要考慮到執行緒池所進行的工作的性質: IO密集型 CPU密集型 簡單的分析來看,如果是CPU密集

lock Mutex Monitor 之間的區別詳解, .net 多執行 同步非同步操作,鎖

Framework為我們提供了三個加鎖的機制,分別是Monitor類、Lock關 鍵字和Mutex類。   總體而言,lock和monitor可以鎖定物件,也可以鎖定函式;而mutex一般用於鎖定函式,並保證不同執行緒間同步呼叫函式,而不會受執行緒優先順序影響。使用lo

Java中實現執行同步的幾種常用方式

首先講一下為什麼要實現執行緒同步: java允許多執行緒併發控制,當多個執行緒同時操作一個可共享的資源變數時(如資料的增刪改查),  將會導致資料不準確,相互之間產生衝突,因此加入同步鎖以避免在該執行緒沒有完成操作之前,被其他執行緒的呼叫, 從而保證了該變數的唯一性和準

執行同步(互斥鎖訊號量的作用區別

“訊號量用在多執行緒多工同步的,一個執行緒完成了某一個動作就通過訊號量告訴別的執行緒,別的執行緒再進行某些動作(大家都在semtake的時候,就阻塞在 哪裡)。而互斥鎖是用在多執行緒多工互斥的,一個執行緒佔用了某一個資源,那麼別的執行緒就無法訪問,直到這個執行緒unloc

雜談(第1篇) | 程序、執行、協程的區別聯絡

作為程式設計師,在面試的時候經常被問到:說說程序、執行緒、協程的區別。下面我們就總結一下。 1.面試答案     1.1  程序與執行緒的區別 總述:執行緒是程序的一個實體,一個程序至少有一個執行緒。 1.根本區別;程序是作業系統資源分配的基本

執行同步鎖和非同步鎖的幾種方式

同步鎖:當在一個java虛擬機器多個執行緒操作一個變數的時候就會出現執行緒安全問題,這個時候就會用到同步鎖。 同步鎖的解決方式: 先看下一個執行緒異常的售票 public class ThreadSafe { public static void main(String[] arg