QT 信号量QSemaphore的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT 信号量QSemaphore的使用相关的知识,希望对你有一定的参考价值。

生产者——消费者模型中,生产者和消费者线程之间需要传递一定量的数据,两个线程会使用一个特定大小的共享环形缓冲器。
生产者向缓冲器中写入数据,直到它到达缓冲器的终点;然后它会再次从起点重新开始,覆盖已经存在的数据。消费者线程则会读取生成的数据。
在生产者——消费者实例中,对于同步的需求有两个部分:如果生产者线程生成数据的速度太快,那么将会把消费者线程还没有读取的数据覆盖;如果消费者线程读取数据的速度过快,那么它就会越过生产者线程而读取一些垃圾数据。
解决这一问题的一个粗略方法是,让生产者线程填满缓冲器,然后等待消费者线程读取完缓冲器中全部速度。
另一个更有效的方案是使用两个信号量。
freeSpace信号量控制生产者线程写入数据的那部分缓冲器,usedSpace信号量则控制消费者线程读取数据的那部分缓冲器区域。这两个区域是相互补充的。常用缓冲区容量值初始化freeSpace信号量,意味着它最多可以获取的缓冲器资源量。在启动这个应用程序时,消费者线程就会获得自由的字节并把它们转换为用过的字节。用0初始化usedSpace信号量,以确保消费者线程不会在一开始就读取到垃圾数据。
在生产者线程中,每次反复写入都是从获取一个自由字节开始。如果该缓冲器中充满了消费者线程还没有读取的数据,那么对acquire()的调用就会被阻塞,直到消费者线程开始消费这些数据。一旦生产者线程获取这一字节,就写入数据,并将这个字节释放为用过的字节,以让消费者线程读取到。
在消费者线程中,我们从获取一个用过的字节开始。如果缓冲器中还没有任何可用的数据,那么将会阻塞对acquire()调用,直到生产者线程生产数据。一旦获取到这个字节,就使用数据,并把字节释放为自由的字节,这样,生产者线程就可以再次写入。

生产者把自由的空间转换为用过的空间,消费者将用过的空间转换为自由的空间。

 

[cpp] view plain copy 技术分享技术分享

  1. /************************************** 

  2. *说明:生产者——消费者线程模型 

  3. ***************************************/  

  4. #include <QtCore/QCoreApplication>  

  5. #include <QSemaphore>  

  6. #include <QThread>  

  7. #include <stdio.h>  

  8. //  

  9. QSemaphore usedSem(0);//已用量  

  10. QSemaphore unusedSem(4096);//未使用变量  

  11. unsigned int buffer[4096];//缓冲区  

  12. //生产者线程  

  13. class producer:public QThread  

  14. {  

  15. public:  

  16.     producer();  

  17. private:  

  18.     void run();  

  19. };  

  20. producer::producer()  

  21. {  

  22.     ;  

  23. }  

  24. //  

  25. void producer::run()  

  26. {  

  27.     int i=0;  

  28.     for(i=0;i<10000;i++)  

  29.     {  

  30.         unusedSem.acquire();//空闲信号量减1  

  31.         buffer[i%4096]=i;  

  32.         usedSem.release();//已用信号量加1  

  33.     }  

  34. }  

  35. //消费者线程  

  36. class customer:public QThread  

  37. {  

  38. public:  

  39.     customer();  

  40. private:  

  41.     void run();  

  42. };  

  43. customer::customer()  

  44. {  

  45.     ;  

  46. }  

  47.   

  48. void customer::run()  

  49. {  

  50.     int i=0;  

  51.     for(i=0;i<10000;i++)  

  52.     {  

  53.         usedSem.acquire();//已用信号量减1  

  54.         printf("%d\n",buffer[i%4096]);  

  55.         unusedSem.release();//空闲信号量加1  

  56.     }  

  57. }  

  58.   

  59. //  

  60. int main(int argc, char *argv[])  

  61. {  

  62.     QCoreApplication a(argc, argv);  

  63.     //  

  64.     producer producerThread;  

  65.     customer customerThread;  

  66.     //  

  67.     producerThread.start();  

  68.     customerThread.start();  

  69.     //  

  70.     producerThread.wait();  

  71.     customerThread.wait();  

  72.     //  

  73.     return a.exec();  

  74. }  


以上是关于QT 信号量QSemaphore的使用的主要内容,如果未能解决你的问题,请参考以下文章

QT 信号量QSemaphore的使用

Qt同步线程(QMutex QMutexLocker QReadWriteLock QSemaphore QWaitCondition )

Qt同步线程(比较清楚,而且QMutex QMutexLocker QReadWriteLock QSemaphore QWaitCondition 每个都有例子)

尝试获取 QSemaphore 时互斥锁解锁失败

QSystemSemaphore 系统级信号量

Qt基础之十四:线程同步