1. 程式人生 > >多執行緒程式設計同步問題

多執行緒程式設計同步問題

實現機制有:1 互斥鎖 2 訊號量 3 條件變數

一、 為什麼要用多執行緒技術?

1、避免阻塞,大家知道,單個程序只有一個主執行緒,當主執行緒阻塞的時候,整個程序也就阻塞了,無法再去做其它的一些功能了。

2、避免CPU空轉,應用程式經常會涉及到RPC,資料庫訪問,磁碟IO等操作,這些操作的速度比CPU慢很多,而在等待這些響應時,CPU卻不能去處理新的請求,導致這種單執行緒的應用程式效能很差。

3、提升效率,一個程序要獨立擁有4GB的虛擬地址空間,而多個執行緒可以共享同一地址空間,執行緒的切換比程序的切換要快得多。

下面給出個多執行緒程式,一個最簡單的模擬售票系統,程式碼如下:

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. void *ticketsell1(void *);  
  4. void *ticketsell2(void *);  
  5. int tickets = 20;  
  6. int main()  
  7. {  
  8.     pthread_t id1,id2;  
  9.     int error;  
  10.     error = pthread_create(&id1, NULL, ticketsell1, NULL);  
  11.     if(error != 0)  
  12.     {  
  13.         printf("pthread is not created!\n");  
  14.         return
     -1;  
  15.     }  
  16.     error = pthread_create(&id2, NULL, ticketsell2, NULL);  
  17.     if(error != 0)  
  18.     {  
  19.         printf("pthread is not created!\n");  
  20.         return -1;  
  21.     }  
  22.     pthread_join(id1,NULL);  
  23.     pthread_join(id2,NULL);  
  24.     return 0;  
  25. }  
  26. void *ticketsell1(void *arg)  
  27. {  
  28.     while(1)  
  29.     {  
  30.         if(tickets > 0)  
  31.         {  
  32. //          usleep(1000);
  33.             printf("ticketse1 sells ticket:%d\n",tickets--);  
  34.         }  
  35.         else
  36.         {  
  37.             break;  
  38.         }  
  39.     }  
  40.     return (void *)0;  
  41. }  
  42. void *ticketsell2(void *arg)  
  43. {  
  44.     while(1)  
  45.     {  
  46.         if(tickets > 0)  
  47.         {  
  48. //          usleep(1000);
  49.             printf("ticketse2 sells ticket:%d\n",tickets--);  
  50.         }  
  51.         else
  52.         {  
  53.             break;  
  54.         }  
  55.     }  
  56.     return (void *)0;  
  57. }  

執行結果如下:

  1. [email protected]:~/qiang/mthread$ ./mthread1   
  2. ticketse2 sells ticket:20  
  3. ticketse2 sells ticket:19  
  4. ticketse2 sells ticket:18  
  5. ticketse2 sells ticket:17  
  6. ticketse2 sells ticket:16  
  7. ticketse2 sells ticket:15  
  8. ticketse2 sells ticket:14  
  9. ticketse2 sells ticket:13  
  10. ticketse2 sells ticket:12  
  11. ticketse2 sells ticket:11  
  12. ticketse2 sells ticket:10  
  13. ticketse2 sells ticket:9  
  14. ticketse2 sells ticket:8  
  15. ticketse2 sells ticket:7  
  16. ticketse2 sells ticket:6  
  17. ticketse2 sells ticket:4  
  18. ticketse2 sells ticket:3  
  19. ticketse2 sells ticket:2  
  20. ticketse2 sells ticket:1  
  21. ticketse1 sells ticket:5  

看到結果,我們發現時能正常賣票的,一部分連續是sel2,另一部分是ticketsel1;

此時,其實存在一個隱含的問題,就是執行緒間的切換,在單CPU系統中,CPU是有時間片時間,時間片到了,就要執行其它的執行緒,假設thread1執行到if裡面,但在printf執行前發生了執行緒切換,那麼會發生什麼呢?我們在這裡用usleep函式(放開程式中的usleep註釋行)進行強制模擬切換;

我們看看結果:

  1. [email protected]:~/qiang/mthread$ gcc -o mthread1 mthread1.c -lpthread  
  2. [email protected]:~/qiang/mthread$ ./mthread1   
  3. ticketse2 sells ticket:20  
  4. ticketse1 sells ticket:19  
  5. ticketse2 sells ticket:18  
  6. ticketse1 sells ticket:17  
  7. ticketse2 sells ticket:16  
  8. ticketse1 sells ticket:15  
  9. ticketse2 sells ticket:14  
  10. ticketse1 sells ticket:13  
  11. ticketse2 sells ticket:12  
  12. ticketse1 sells ticket:11  
  13. ticketse2 sells ticket:10  
  14. ticketse1 sells ticket:9  
  15. ticketse2 sells ticket:8  
  16. ticketse1 sells ticket:7  
  17. ticketse2 sells ticket:6  
  18. ticketse1 sells ticket:5  
  19. ticketse2 sells ticket:4  
  20. ticketse1 sells ticket:3  
  21. ticketse1 sells ticket:2  
  22. ticketse2 sells ticket:1  
  23. ticketse1 sells ticket:0  
  24. [email protected]:~/qiang/mthread$   

執行程式發現竟然有0號票被賣出了,這顯然是錯誤的!當thread1的if裡面發生執行緒切換時,thread2得到執行,把最後一張票賣了,此時thread1恢復執行,結果賣出了0號票,這裡我們需要的是火車票的票數資料對於所有執行緒而言是同步的,所以就要用到執行緒同步技術了。

三、  使用多執行緒的同步與互斥

1、多執行緒的同步方式有很多種,例如互斥鎖,條件變數,訊號量,讀寫鎖。先看看互斥鎖如何解決多執行緒之間的同步問題。程式用互斥鎖後如下:

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. void *ticketsell1(void *);  
  4. void *ticketsell2(void *);  
  5. int tickets = 20;  
  6. pthread_mutex_t mutex;  
  7. int main()  
  8. {  
  9.     pthread_t id1,id2;  
  10.     pthread_mutex_init(&mutex, NULL);//
  11.     int error;  
  12.     error = pthread_create(&id1, NULL, ticketsell1, NULL);  
  13.     if(error != 0)  
  14.     {  
  15.         printf("pthread is not created!\n");  
  16.         return -1;  
  17.     }  
  18.     error = pthread_create(&id2, NULL, ticketsell2, NULL);  
  19.     if(error != 0)  
  20.     {  
  21.         printf("pthread is not created!\n");  
  22.         return -1;  
  23.     }  
  24.     pthread_join(id1,NULL);  
  25.     pthread_join(id2,NULL);  
  26.     return 0;  
  27. }  
  28. void *ticketsell1(void *arg)  
  29. {  
  30.     while(1)  
  31.     {  
  32. 相關推薦

    執行程式設計同步問題

    實現機制有:1 互斥鎖 2 訊號量 3 條件變數一、 為什麼要用多執行緒技術?1、避免阻塞,大家知道,單個程序只有一個主執行緒,當主執行緒阻塞的時候,整個程序也就阻塞了,無法再去做其它的一些功能了。2、避免CPU空轉,應用程式經常會涉及到RPC,資料庫訪問,磁碟IO等操作,這

    linux執行程式設計——同步與互斥

    我們在前面文章中已經分析了多執行緒VS多程序,也分析了執行緒的使用,現在我們來講解一下linux多執行緒程式設計之同步與互斥。 現在,我們不管究竟是多執行緒好還是多程序好,先講解一下,為什麼要使用多執行緒? 一、 為什麼要用多執行緒技術? 1、避免阻塞,大家知道,單個程序只

    linux執行程式設計 同步與互斥

    ——本文一個例子展開,介紹Linux下面執行緒的操作、多執行緒的同步和互斥。 前言 執行緒?為什麼有了程序還需要執行緒呢,他們有什麼區別?使用執行緒有什麼優勢呢?還有多執行緒程式設計的一些細節問題,如執行緒之間怎樣同步、互斥,這些東西將在本文中介紹。我在某QQ群裡見到這樣一道面試題: 是否熟悉POSIX多

    Java執行程式設計執行同步與互斥/執行安全/Java鎖

    摘要:多執行緒三個特徵:原子性、可見性以及有序性.&gt;執行緒的同步與互斥?(同步執行緒與非同步執行緒,執行緒同步和非同步問題)&nbsp;&nbsp;1.同步:假設現有執行緒A和執行緒B,執行緒A需要往緩衝區寫資料,執行緒B需要從緩衝區讀資料,但他們之間存在一種制約

    Linux執行程式設計---執行同步(互斥鎖、條件變數、訊號量和讀寫鎖)

    本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。  下面是思維導

    java執行程式設計之使用Synchronized塊同步變數

    通過synchronized塊來同步特定的靜態或非靜態方法。 要想實現這種需求必須為這些特性的方法定義一個類變數,然後將這些方法的程式碼用synchronized塊括起來,並將這個類變數作為引數傳入synchronized塊   下面的程式碼演示瞭如何同步特定的類方法:

    學習筆記-執行程式設計執行同步

        執行緒基礎  程序與執行緒 我們執行一個exe,就是一個程序例項,系統中有很多個程序。每一個程序都有自己的記憶體地址空間,每個程序相當於一個獨立的邊界,有自己的獨佔的資源,程序之間不能共享程式碼和資料空間。 每一個程序有一個或多個執行緒,程

    Java執行程式設計筆記2:synchronized同步方法

    非執行緒安全會在多個執行緒對同一個物件中的例項變數進行併發訪問時發生,產生的結果就是髒讀,也就是取到的資料是被更改過的。執行緒安全就是獲得的例項變數的值是經過同步處理的。 方法內的變數是執行緒安全的 方法內的變數是執行緒安全的。非執行緒安全的問題存在於例項變數中,如果是方法內部的私有變數,不存在非執行緒安

    Java執行程式設計--使用Lock物件實現同步以及執行間通訊

    前幾篇: 在《Java多執行緒程式設計-(4)-執行緒間通訊機制的介紹與使用》已經學習了,可以使用方法wait/notify 結合同步關鍵字syn

    Java執行程式設計-(5)-使用Lock物件實現同步以及執行間通訊

    前幾篇: 在《Java多執行緒程式設計-(4)-執行緒間通訊機制的介紹與使用》已經學習了,可以使用方法wait/notify 結合同步關鍵字syn

    C++11執行程式設計 第十章: 使用packaged_task優雅的讓同步函式非同步執行

    C++11 Multithreading – Part 10: packaged_task<> Example and Tutorial Varun July 2, 2017 C++11 Multithreading – Part 10: packaged_tas

    Java執行程式設計-(12)-Java中的佇列同步器AQS和ReentrantLock鎖原理簡要分析

    原文出自 : https://blog.csdn.net/xlgen157387/article/details/78341626 一、Lock介面 在上一篇文章中: Java多執行緒程式設計-(5)-使用Lock物件實現同步以及執行緒間通訊 介紹

    Linux執行同步機制 .linux執行程式設計機制

    #include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_mutex_t mutex; pthread_cond_t  cond; void * child1(void *arg) {      

    Linux下的執行程式設計二(執行同步與互斥)

    一、什麼叫做執行緒的同步與互斥?為什麼需要同步與互斥? 1、同步與互斥 互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。 同步:是指在互斥的基礎上(大多數情況),通過其它機制

    C++——執行程式設計(二)std::mutex 執行同步、解決資源競爭問題

    前言 執行緒同步 這裡的“同”不是同時、一起執行的意思,而是指協同、協助、互相配合。執行緒同步是指多個執行緒協同步調,按預定的先後次序進行執行。 執行緒A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B執行;B依言執行,再將結果給A;

    JAVA併發:執行程式設計同步“監視器monitor”(三)

    在JAVA虛擬機器中,每個物件(Object和class)通過某種邏輯關聯監視器,為了實現監視器的互斥功能,每個物件(Object和class)都關聯著一個鎖(有時也叫“互斥量”),這個鎖在作業系統書籍中稱為“訊號量”,互斥(“mutex”)是一個二進位制的訊號量。 如果一個執行緒擁有了某些資料的鎖,其他的

    執行 共享資源 同步鎖 java Java執行程式設計:Lock

    Java多執行緒程式設計:Lock   synchronized是java中的一個關鍵字,也就是說是Java語言內建的特性。那麼為什麼會出現Lock呢?   如果一個程式碼塊被synchronized修飾了,當一個執行緒獲取了對應的鎖,並執行該程式碼塊時,其他執行緒便只

    windows C++執行程式設計高階篇 實現執行同步

        上一篇文章windows程式設計 使用C++實現多執行緒類僅僅是介紹了怎樣用類來實現多執行緒,這篇文章則重點介紹多執行緒中資料同步的問題。好了,廢話不多說,進入主題。     問題場景:這裡我們假設有這樣一個工作流水線(CWorkPipeline),它不斷的生成一

    VC++執行程式設計-執行間的通訊和執行同步

    執行緒間通訊   一般而言,應用程式中的一個次要執行緒總是為主執行緒執行特定的任務,這樣,主執行緒和次要執行緒間必定有一個資訊傳遞的渠道,也就是主執行緒和次要執行緒間要進行通訊。這種執行緒間的通訊不但是難以避免的,而且在多執行緒程式設計中也是複雜和頻繁的,下面將進行說明。

    Linux程式設計學習筆記----執行程式設計執行同步機制之互斥量(鎖)與讀寫鎖

    互斥鎖通訊機制 基本原理 互斥鎖以排他方式防止共享資料被併發訪問,互斥鎖是一個二元變數,狀態為開(0)和關(1),將某個共享資源與某個互斥鎖邏輯上繫結之後,對該資源的訪問操作如下: (1)在訪問該資源之前需要首先申請互斥鎖,如果鎖處於開狀態,則申請得到鎖並立即上鎖(關),防