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

版权声明:课程笔记内容整理于狄泰软件 https://blog.csdn.net/qq_39654127/article/details/81947446

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

第76课 - 多线程间的互斥(下)

猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/81947446