唯快不破:【多執行緒】使用訊號量進行同步
p操作和v操作是不可中斷的程式段,稱為原語。P,V原語中P是荷蘭語的Passeren,相當於英文的pass, V是荷蘭語的Verhoog,相當於英文中的incremnet。
且在P,V願語執行期間不允許有中斷的發生。
首先應弄清PV操作的含義:PV操作由P操作原語和V操作原語組成(原語是不可中斷的過程),對訊號量進行操作,具體定義如下:
P(S):①將訊號量S的值減1,即S=S-1;②如果S>=0,則該程式繼續執行;否則該程式置為等待狀態,排入等待佇列。
V(S):①將訊號量S的值加1,即S=S+1;②如果S>0,則該程式繼續執行;否則釋放佇列中第一個等待訊號量的程式。
PV操作的意義:我們用訊號量及PV操作來實現程式的同步和互斥。PV操作屬於程式的低階通訊。
什麼是訊號量?訊號量(semaphore)的資料結構為一個值和一個指標,指標指向等待該 訊號量的下一個程式。訊號量的值與相應資源的使用情況有關。當它的值大於0時,表示當前可用資源的數量;當它的值小於0時,其絕對值表示等待使用該資源的程式個數。注意,訊號量的值僅能由PV操作來改變。
一般來說,訊號量S>=0時,S表示可用資源的數量。執行一次P操作意味著請求分配一個單位資源,因此S的值減1;
當S<0時,表示已經沒有可用資源,請求者必須等待別的程式釋放該類資源,它才能執行下去。而執行一個V操作意味著釋放一個單位資源,因此S的值加1;
若S<=0,表示有某些程式正在等待該資源,因此要喚醒一個等待狀態的程式,使之執行下去。
對訊號量有4種操作(include<semaphore>):
1. 初始化(initialize),int set_init(sem_t *sem, int pshared, unsigned int value);//第二引數為0表示程式間不共享
2. 等訊號(wait),int sem_wait(sem_t *sem);//訊號量大於1時,減一併返回;小於1時執行緒阻塞。
3. 給訊號(signal)int sem_post(sem_t *sem);//訊號量加一
4. 清理(destory) int sem_destory(sem_t *sem);
使用訊號量實現生產者-消費者例子:
- #define BUFFER_SIZE 16 // 緩衝區數量
- struct prodcons
- {
- // 緩衝區相關資料結構
- int buffer[BUFFER_SIZE]; /* 實際資料存放的陣列*/
- int readpos, writepos; /* 讀寫指標*/
- sem_t empty; /* 緩衝區非空的條件變數 */
- sem_t occupied; /* 緩衝區未滿的條件變數 */
- sem_t s_put;/*輸入互斥訊號量*/
- sem_t s_take;/*取出互斥訊號量*/
- };
- /* 初始化緩衝區結構 */
- void init(struct prodcons *b)
- {
- b->readpos = 0;
- b->writepos = 0;
- sem_init(&b->empty,0,BUFFER_SIZE);
- sem_init(&b->occupied,0,0);
- sem_init(&b->s_put,0,1);//二進位制訊號量,相當於互斥鎖
- sem_init(&b->s_take,0,1);
- }
- /* 將產品放入緩衝區,這裡是存入一個整數*/
- void put(struct prodcons *b, int data)
- {
- /*檢視空位訊號量,是否可以放入產品*/
- sem_wait(&b->empty);
- /*檢視是否有其他執行緒正在放入,同一時刻只能一個執行緒放入*/
- sem_wait(&b->s_put);
- /* 寫資料,並移動指標 */
- b->buffer[b->writepos] = data;
- b->writepos++;
- if (b->writepos >= BUFFER_SIZE)
- b->writepos = 0;
- sem_post(&b->s_put);//解除互斥
- sem_post(&b->occupied);//放入完成,被佔位置訊號量加一
- }
- /* 從緩衝區中取出整數*/
- int get(struct prodcons *b)
- {
- int data;
- /*檢視被佔訊號量,是否有產品可以拿出*/
- sem_wait(&b->occupied);
- /*檢視是否有其他執行緒正在拿出,同一時刻只能一個執行緒拿出*/
- sem_wait(&b->s_take);
- /* 讀資料,移動讀指標*/
- data = b->buffer[b->readpos];
- b->readpos++;
- if (b->readpos >= BUFFER_SIZE)
- b->readpos = 0;
- sem_post(&b->s_take);//解除互斥
- sem_post(&b->empty);//拿出完成,被空位訊號量加一
- return data;
- }
- /* 測試:生產者執行緒將1 到100 的整數送入緩衝區,消費者線
- 程從緩衝區中獲取整數,兩者都列印資訊*/
- #define OVER ( - 1)
- struct prodcons buffer;
- void *producer(void *data)
- {
- int n;
- for (n = 0; n < 100; n++)
- {
- printf("%d --->\n", n);
- put(&buffer, n);
- } put(&buffer, OVER);
- return NULL;
- }
- void *consumer(void *data)
- {
- int d;
- while (1)
- {
- d = get(&buffer);
- if (d == OVER)
- break;
- printf("--->%d \n", d);
- }
- return NULL;
- }
- int main(void)
- {
- pthread_t th_a, th_b;
- void *retval;
- init(&buffer);
- /* 建立生產者和消費者執行緒*/
- pthread_create(&th_a, NULL, producer, 0);
- pthread_create(&th_b, NULL, consumer, 0);
- /* 等待兩個執行緒結束*/
- pthread_join(th_a, &retval);
- pthread_join(th_b, &retval);
- return 0;
- }
- <span style="font-family:'KaiTi_GB2312';font-size:18px;"><strong>
- </strong></span>
互斥鎖和訊號量的區別:
互斥鎖:
互斥鎖是一種保護機制。上鎖後其他執行緒不能進入保護區域的程式碼,直到鎖被釋放。
訊號量:
訊號量是一種同步機制。訊號量的值代表可用的資源數目,當值大於0代表有可用資源,則允許繼續操作,否則執行緒阻塞,等待可用資源。
當可用資源是1時,訊號量與互斥鎖基本沒區別,都起保護作用。當資源數大於1,則當訊號量大於0時執行緒都可進行操作。如果資源大於1時使用互斥鎖,則就算資源數大於1時,也只能有一個執行緒進入操作,其餘執行緒必須阻塞。
訊號量可用於程式通訊和執行緒通訊,而互斥鎖只能用於執行緒通訊。
但是還是覺得互斥鎖就可以認為是訊號量的特例。
現在有種突然明白什麼是利用訊號量進行多執行緒同步的含義了。
http://blog.csdn.net/yusiguyuan/article/details/14110437
相關文章
- windows多執行緒同步--訊號量Windows執行緒
- Java多執行緒—執行緒同步(單訊號量互斥)Java執行緒
- iOS多執行緒非同步訊號量iOS執行緒非同步
- 執行緒同步(windows平臺):訊號量執行緒Windows
- windows多執行緒同步--互斥量Windows執行緒
- Swift多執行緒:GCD進階,單例、訊號量、任務組Swift執行緒GC單例
- Java多執行緒學習(3)執行緒同步與執行緒通訊Java執行緒
- Swift多執行緒:使用Thread進行多執行緒間通訊,協調子執行緒任務Swift執行緒thread
- 多執行緒同步執行緒
- 多執行緒Demo學習(執行緒的同步,簡單的執行緒通訊)執行緒
- VC訊號量和執行緒的用法執行緒
- JavaThread多執行緒同步、鎖、通訊Javathread執行緒
- Java多執行緒-執行緒通訊Java執行緒
- java 多執行緒 –同步Java執行緒
- java 多執行緒 --同步Java執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- Java多執行緒/併發11、執行緒同步通訊:notify、waitJava執行緒AI
- 關於c#多執行緒中的幾個訊號量C#執行緒
- C++ 多執行緒框架 (2):Mutex 互斥和 Sem 訊號量C++執行緒框架Mutex
- 4、Linux多執行緒,執行緒同步(2)Linux執行緒
- 多執行緒(2)-執行緒同步互斥鎖Mutex執行緒Mutex
- 產品行業,唯快不破?行業
- qt多執行緒訊號槽傳輸方式QT執行緒
- C#多執行緒開發-執行緒同步 02C#執行緒
- #大學#Java多執行緒學習02(執行緒同步)Java執行緒
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- java多執行緒–同步鎖Java執行緒
- 多執行緒 -- 同步器執行緒
- windows多執行緒同步--事件Windows執行緒事件
- 多執行緒同步的原理執行緒
- 非同步VS多執行緒非同步執行緒
- Java多執行緒併發工具類-訊號量Semaphore物件講解Java執行緒物件
- java-多執行緒-CountDownLatch(閉鎖) CyclicBarrier(柵欄) Semaphore(訊號量)-Java執行緒CountDownLatch
- 非同步/同步,阻塞/非阻塞,單執行緒/多執行緒概念梳理非同步執行緒
- python多執行緒程式設計3: 使用互斥鎖同步執行緒Python執行緒程式設計
- 使用Windows API和多執行緒進行串列埠通訊[1] (轉)WindowsAPI執行緒串列埠
- Java多執行緒學習——執行緒通訊Java執行緒
- JAVA多執行緒詳解(3)執行緒同步和鎖Java執行緒