多线程的互斥(下)——信号量
多线程 互斥 信号量
2023-09-14 09:12:37 时间
信号量的概念
-信号量是特殊的线程锁
-信号量允许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 )
相关文章
- Scheduled定时器配置类,配置多线程执行定时任务(解决多个定时任务同时执行有可能会失效的问题)
- C++多线程编程:同步之互斥量Mutex「建议收藏」
- Java 多线程并发编程之互斥锁 Reentrant Lock详解编程语言
- Linux下实现多线程互斥技术研究(linux多线程互斥)
- Linux C语言实现多线程编程技术简介(linuxc语言多线程)
- Linux调试:管理多线程的完美技巧(linux调试线程)
- 锁Linux共享内存互斥锁:解决多线程同步问题(linux共享内存互斥)
- Linux互斥锁:解决多线程同步问题(linux互斥锁使用)
- Linux下实现多线程操作的同步和互斥机制(linux线程同步与互斥)
- 持久化MongoDB:用多线程实现数据持久化(mongodb多线程)
- 易语言搭建多线程MSSQL服务器(易语言mssql多线程)
- Linux服务端如何利用多线程提高运行效率。(linux服务端多线程)
- 洞悉Redis多线程魅力深入理解(怎么理解redis多线程)
- 基于多线程的Redis存储技术(多线程存储到redis)
- java多线程并发executorservice(任务调度)类