多线程的互斥(下)——信号量

信号量的概念

-信号量是特殊的线程锁

-信号量允许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 )

原文地址:https://www.cnblogs.com/-glb/p/13457567.html