1. 程式人生 > 實用技巧 >多執行緒的互斥(下)——訊號量

多執行緒的互斥(下)——訊號量

訊號量的概念

-訊號量是特殊的執行緒鎖

-訊號量允許N個執行緒同時訪問臨界資源

-Qt中直接支援訊號量(QSemaphore)

執行緒鎖是用來保護臨界資源的,每個執行緒鎖每次只允許一個執行緒進行訪問臨界資源。

QSemaphore sem(1)定義了一個訊號量,並且N的值為1,意味著一次只允許一個執行緒去訪問臨界資源。

sem.acquire()當前執行緒嘗試著獲取這個特殊的執行緒鎖,首先到該函式中檢視n的值是不是大於0的,如果是的話,就可以獲取這把特殊的執行緒鎖。如果n的值為0,那就必須等待。

再論生產消費者的問題:

在前面的實驗中已經做過一個生產者,一個消費者,一個倉庫。在本課程中實現n個生產者,n個消費者,n個倉庫。如何做到併發高效性呢,此時就需要使用QSemphore訊號量了。

#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QSemaphore>

const int SIZE = 5; //用來定義倉庫的個數
unsigned char g_bufer[SIZE] = {0};
QSemaphore g_sem_free(SIZE);  //表示5個倉庫都是空閒的
QSemaphore g_sem_used(0);   //初始值為0,表示有多少個倉庫已經被使用了

class Producer : public QThread
{
protected: void run() { while(true) { int value = qrand()%100; g_sem_free.acquire(); for(int i=0; i<SIZE; i++) { if( !g_bufer[i] ) { g_bufer[i] = value; qDebug()
<< objectName() << "generate (" << i << "," << value << ")" << endl; break; } } g_sem_used.release(); sleep(2); } } }; class Consumer : public QThread { protected: void run() { while(true) { g_sem_used.acquire(); for(int i=0; i<SIZE; i++) { if( g_bufer[i] ) { int value = g_bufer[i]; g_bufer[i] = 0; qDebug() << objectName() << "consume (" << i << "," << value << ")" <<endl; break; } } g_sem_free.release(); sleep(2); } } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Producer p1; Producer p2; Producer p3; Consumer c1; Consumer c2; p1.setObjectName("p1"); p2.setObjectName("p2"); p3.setObjectName("p3"); c1.setObjectName("c1"); c2.setObjectName("c2"); p1.start(); p2.start(); p3.start(); c1.start(); c2.start(); return a.exec(); }

列印結果如下:

"p1" generate ( 1 , 41 )

"p3" generate ( 2 , 41 )

"p2" generate ( 0 , 41 )

"c2" consume ( 1 , 41 )

"c1" consume ( 0 , 41 )

"p2" generate ( 0 , 67 )

"p3" generate ( 1 , 67 )

"p1" generate ( 3 , 67 )

"c1" consume ( 1 , 67 )

"c2" consume ( 0 , 67 )

"p2" generate ( 0 , 34 )

"p3" generate ( 1 , 34 )

"p1" generate ( 4 , 34 )

"c1" consume ( 1 , 34 )

"c2" consume ( 0 , 34 )

"p2" generate ( 0 , 0 )

"p3" generate ( 0 , 0 )

"c1" consume ( 2 , 41 )

"c2" consume ( 3 , 67 )

"p1" generate ( 0 , 0 )

"p2" generate ( 0 , 69 )

"c1" consume ( 0 , 69 )

"p3" generate ( 0 , 69 )

"c2" consume ( 0 , 69 )

"p1" generate ( 0 , 69 )

"c1" consume ( 0 , 69 )

"p2" generate ( 0 , 24 )

"c2" consume ( 0 , 24 )

"p3" generate ( 0 , 24 )

"c1" consume ( 0 , 24 )

"p1" generate ( 0 , 24 )

"c2" consume ( 0 , 24 )

"p2" generate ( 0 , 78 )

"c1" consume ( 0 , 78 )

"p3" generate ( 0 , 78 )

"c2" consume ( 0 , 78 )

"p2" generate ( 0 , 58 )

"c1" consume ( 0 , 58 )

"p1" generate ( 0 , 78 )

"c2" consume ( 0 , 78 )

"p3" generate ( 0 , 58 )

"c1" consume ( 0 , 58 )

""p2" generate ( 0 , 62 )

c2" consume ( 4 , 34 )

"p1" generate ( 1 , 58 )

"c1" consume ( 0 , 62 )

"p3" generate ( 0 , 62 )

"c2" consume ( 0 , 62 )

"p1" generate ( 0 , 62 )

"c1" consume ( 0 , 62 )

"p2" generate ( 0 , 64 )

"c2" consume ( 0 , 64 )

"p3" generate ( 0 , 64 )

"c1" consume ( 0 , 64 )

"p1" generate ( 0 , 64 )

"c2" consume ( 0 , 64 )

"p3" generate ( 0 , 5 )

"c1" consume ( 0 , 5 )

"p2" generate ( 0 , 5 )

"c2" consume ( 0 , 5 )

"p1" generate ( 0 , 5 )

"c1" consume ( 0 , 5 )

"p3" generate ( 0 , 45 )

"c2" consume ( 0 , 45 )

"p2" generate ( 0 , 45 )

"c1" consume ( 0 , 45 )

"p1" generate ( 0 , 45 )

"c2" consume ( 0 , 45 )

"p3" generate ( 0 , 81 )