第七十五课、多线程间的互斥(上)------------------狄泰软件学院

一、多线程间的互斥

1、生产消费者问题

(1)、有n个生产者同时制造产品,并把产品放入仓库中

(2)、有m个消费者同时从仓库中取出产品

(3)、规则

A、当仓库未满,任意生产者可以存入产品

B、当仓库未空,任意消费者可以取出产品

2、生活中的线程互斥例子

标示牌用于指示是否可用:

红绿灯标识十字路口是否可用:

3、线程互斥的相关概念

(1)、临界资源(Critical Resource):每次只允许一个线程访问(读/写)的资源

(2)、线程间的互斥(竞争):多个线程在同一个时间都需要访问临界资源

(3)、QMutex类是一把线程锁,保证线程间的互斥:利用线程锁能够保证临界资源的安全性

4、QMutex中的关键成员函数(锁就是类似上面两个生活中例子的标识

(1)、void lock()

A、当锁空闲时,获取锁并继续执行

B、当锁别人被获取,堵塞并等待锁释放

(2)、void unlock()

A、释放锁同一把锁的获取和释放必须在同一线程中成对出现

#include <QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QDebug>

#define MAXSTORAGE 10 //最大仓库容量

static QMutex g_mutex;
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));//产生的数字总是在0-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.count()>0)
            {
                g_store.remove(0, 1);

                qDebug() << objectName() << ":" + g_store;
            }

            g_mutex.unlock();

            msleep(1);
        }
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main begin";

    Producer p;
    Customer c;

    p.setObjectName("Produer");
    c.setObjectName("Customer");

    p.start();
    c.start();

    qDebug() << "main end";

    return a.exec();
}
用线程锁解决生产消费者的问题

二、小结

(1)、临界资源每次只允许一个线程访问(读/写)

(2)、线程锁(QMutex)用于保护临界资源

(3)、线程只有获取锁之后才能访问临界资源

(4)、锁被其它线程获取时,当前线程处于等待状态

(5)、线程锁的获取和释放必须在同一线程中成对出现

posted @ 2017-02-26 10:12  lgc202  阅读(757)  评论(0编辑  收藏  举报