多執行緒的互斥(下)——訊號量
阿新 • • 發佈:2020-08-08
訊號量的概念
-訊號量是特殊的執行緒鎖
-訊號量允許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 )