1、多线程间的互斥
多个线程间除了在时序上可能产生依赖,
在其它方面是否也可能产生依赖呢?
生产消费者问题
-有n个生产者同时制造产品,并把产品存入仓库中
-有m个消费者同时需要从仓库中取出产品
-规则:
• 当仓库未满,任意生产者可以存入产品
• 当仓库未空,任意消费者可以取出产品
2、编程实验
生成消费者问题 75-1.pro
#include <QtCore/QCoreApplication>
#include <QThread>
#include <QDebug>
static QString g_store; //仓库
class Producer : public QThread//生产者
{
protected:
void run()
{
int count = 0;
while(true)
{
g_store.append(QString::number((count++) % 10));//每次生产0,10之间数字放到仓库
qDebug() << objectName() << " : " + g_store;
msleep(1);
}
}
};
class Customer : public QThread//消费者
{
protected:
void run()
{
while( true )
{
if( g_store != "" )
{
g_store.remove(0, 1);//从仓库删除第一个字符
qDebug() << objectName() << " : " + g_store;
}
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();
}
某一个时间点程序奔溃
生产者与消费者由于竞争产生依赖
生活中的例子
临界资源(Critical Resource)
-每次只允许一个线程进行访问(读/写)的资源
线程间的互斥(竞争)
-多个线程在同一时刻都需要访问临界资源
QMutex类是一把线程锁,保证线程间的互斥
-利用线程锁能够保证临界资源的安全性
QMutex中的关键成员函数
-void lock()
• 当锁空闲时,获取锁并继续执行
• 当锁被获取,阻塞并等待锁释放
-void unlock()
• 释放锁(同一把锁的获取和释放锁必须在同一线程中成对出现)
QMutex使用示例
QMutex mutex;
mutex.lock();
//do something with critical resource
mutex.unlock();
注意:
如果mutex在调用unlock()时处于空闲
状态,那么程序的行为是未定义的!
3、编程实验
解决生产消费者者问题 75-1.pro
#include <QtCore/QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QDebug>
static QMutex g_mutex;
static QString g_store;
class Producer : public QThread
{
protected:
void run()
{
int count = 0;
while(true)
{
g_mutex.lock();
g_store.append(QString::number((count++) % 10));
qDebug() << objectName() << " : " + g_store;
g_mutex.unlock();
msleep(1);
}
}
};
class Customer : public QThread
{
protected:
void run()
{
while( true )
{
g_mutex.lock();
if( g_store != "" )
{
g_store.remove(0, 1);
qDebug() << objectName() << " : " + g_store;
}
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();
}
4、小结
临界资源每次只允许一个线程进行访问(读/写)
线程锁(QMutex)用于保护临界资源
线程只有获取锁之后才能访问临界资源
锁被其他线程获取时,当前线程进入等待状态
线程锁的获取和释放必须在同一线程中成对出现
5、To be continued