第75课 多线程间的互斥(上)

一、多线程间的互斥

                

    1、 生产消费者问题

        1.1、 有n个生产者同时制造产品,并把产品放入仓库中
        1.2、 有m个消费者同时从仓库中取出产品
        1.3、 规则(产品是公共资源,同一时刻只能被一个线程访问)
            A、 当仓库未满,任意生产者可以存入产品
            B、 当仓库未空,任意消费者可以取出产品

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

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


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

        


    3、 线程互斥的相关概念

        3.1、 临界资源(Critical Resource):每次只允许一个线程访问(读/写)的资源
        3.2、 线程间的互斥(竞争):多个线程在同一个时间都需要访问临界资源
        3.3、 QMutex类是一把线程锁,保证线程间的互斥:利用线程锁能够保证临界资源的安全性

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

        4.1、 void lock()
            A、 当锁空闲时,获取锁并继续执行
            B、 当锁被获取,堵塞并等待锁释放

        4.2、 void unlock()
            A、 释放锁同一把锁的获取和释放必须在同一线程中成对出现,类似于new 和 delete

                
用线程锁解决生产者消费者的问题


#include <QtCore/QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QMutex>
#include <QString>
#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);//移除第0个位置的一个字符
                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("Producer");
    c.setObjectName("Customer");
    p.start();
    c.start();
    qDebug() << "main End";
    
    return a.exec();
}



二、小结

    1、 临界资源每次只允许一个线程访问(读/写)
    2、 线程锁(QMutex)用于保护临界资源
    3、 线程只有获取锁之后才能访问临界资源
    4、 锁被其它线程获取时,当前线程处于等待状态
    5、 线程锁的获取和释放必须在同一线程中成对出现(类似,new和delete)





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值