信号量可以理解为互斥量的延伸或者说是互斥量的泛化,一个互斥量只能锁一次,但信号量则可以获取多次,信号量经常在多线程或多进程中用来保护一定数量的共享资源,线程必须要获取一个信号量,举个例子:
有一个餐馆,里面有十个位置, 最初都是空的,这个时候如果进来十二个人,则看门人仅允许十个人进入,然后锁上门,剩下的二个人则必须在大门等待,此后来的所有的顾客也不得不在门口等待,这时如果里面有个人吃完饭离开了,则看门人打开大门,外面的一个人可以进来,如果又有五个人走了,则又可以放外面的五个人进来。在这个例子中,餐馆中的座位是共享资源,而看门人起到了信号量的作用,进去吃饭的人就是一个线程。
在qt中,QSemaphore类代表信号量,他主要有两个基本的操作acquire()和release():acquire()获取资源,如果没有可用的共享资源,则调用该信号量的线程将会阻塞,直到有可以利用的资源为止,release()用来释放资源(调用该接口后,资源数量将会+1)。
const int dataSize = 1000;
const int buffersize = 800;
char buffer[buffersize];
QSemaphore smt_free(buffersize);
QSemaphore smt_used;
//生产者
class CProduce:public QThread
{
Q_OBJECT
public:
CProduce(QObject* parent = nullptr){};
~CProduce(){};
public:
void run()override{
for (int i = 0; i < dataSize;++i)
{
smt_free.acquire();
buffer[i%buffersize] = "ACGR"[(int)(qrand())/4];
smt_used.release();
}
};
}
//消费者
class CConsume:public QThread
{
Q_OBJECT
public:
CConsume(QObject* parent = nullptr){};
CConsume(){};
public:
void run()override{
for (int i = 0; i < dataSize;++i)
{
smt_used.acquire();
fprintf(stderr,"%c",buffer[i%buffersize]);
smt_free.release();
}
};
}
int main(int argc,char*argv[])
{
QCoreApplication a(argc,argv);
CProduce produce;
CConsume consume;
produce.start();
consume.start();
produce.wait();
consume.wait();
return a.exec();
}