第75课 多线程间的互斥(上)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第75课 多线程间的互斥(上)相关的知识,希望对你有一定的参考价值。
1. 生产消费者问题
(1)问题描述
①有n个生产者同时制造产品,并把产品存入仓库中
②有m个消费者同时需要从仓库中取出产品。
(2)规则
①当仓库未满,任意生产者可以存入产品。
②当仓库未空,任意消费者可以取出产品。
2. 生活中的例子
①线程间除了时序上可能存在依赖,还可能读写共享资源时存在依赖。
②洗手间的使用
③“十字路口”
3. 多线程间的互斥
(1)临界资源(Critical Resource):每次只允许一个线程进行访问(读/写)的资源。(注意,这与Windows下的临界区不是一个概念,临界资源是要共享读写的资源)。
(2)线程间的互斥(竞争):多个线程在同一时刻都需要访问临界资源,这时会产生竞争。
(3)QMutex类是一把线程锁,保证线程间的互斥。利用线程锁能够保证临界资源的安全性。
4. QMutex中的关键成员函数
(1)void lock()函数
①当锁空闲时,获取锁并继续执行。
②当锁被其他线程占有时,阻塞并等待锁的释放。
(2)void unlock()函数:
①释放锁(同一把锁的获取和释放必须在同一线程中成对出现)
②如果调用unlock()时处于空闲状态,也就是在调用lock()之前先调用unlock(),那么程序的行为是未定义的。
【编程实验】解决生产消费者问题
#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QDebug> #define MAXSTORAGE 10 //最大库存量 static QMutex g_mutex; //读写库存锁 static QMutex g_debug; //qdebug锁 static QString g_store; //生产者 class Producer : public QThread { protected: void run() { int count = 0; while (true) { g_mutex.lock(); //生产数据,未满仓时将数据加入仓库 if(g_store.count() <= MAXSTORAGE) { g_store.append(QString::number((count++) % 10)); g_debug.lock(); qDebug() << objectName() << ":" + g_store; g_debug.unlock(); } g_mutex.unlock(); msleep(1); } } }; //消费者 class Customer : public QThread { protected: void run() { while (true) { g_mutex.lock(); //仓库 if(g_store.count() > 0) { //字符串中的最前面的1个字符 g_store.remove(0, 1); g_debug.lock(); qDebug() << objectName() << ":" + g_store; g_debug.unlock(); } g_mutex.unlock(); msleep(1); } } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Producer p; Customer c; p.setObjectName("Producer"); c.setObjectName("Customer"); p.start(); c.start(); return a.exec(); }
5. 小结
(1)临界资源每次只允许一个线程进行访问(读/写)
(2)线程锁(QMutex)用于保护临界资源
(3)线程只有获取锁之后才能访问临界资源
(4)锁被其他线程获取时,当前线程进入等待状态。
(5)线程锁的获取和释放必须在同一线程中成对出现。
以上是关于第75课 多线程间的互斥(上)的主要内容,如果未能解决你的问题,请参考以下文章