多线程间的互斥(上)

值得思考的问题:

多个线程除了在时序上可能产生相互依赖,在其他方面是否也可能产生相互依赖呢?

生产消费者问题:
-有n个生产者同时制造产品,并把产品存入仓库中

-有m个消费者同时需要从仓库中取出产品

-规则:

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

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

编程实验:生产消费者问题

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

static QString q_store;    //通过全局变量来模拟唯一的仓库

class Producer : public QThread
{
protected:
    void run()
    {
      int count = 0;
      while(true)
      {
          //每次产生的数字在0-10之间,模拟了生产者将生产好的产品(一个数字)放入到仓库中(一个字符串类的对象)
          q_store.append(QString::number((count++) % 10));
          qDebug() << objectName() << " :" + q_store; //用字符串中字符表示当前仓库中的商品
          msleep(1);
      }
    }

};

class Customer : public QThread
{
protected:
    void run()
    {
        while(true)
        {
            if(q_store != " ")
            {
                q_store.remove(0,1); //删除字符串中的第一个字符,表示取出一个商品
                qDebug() << objectName() << " : " + q_store;
            }
            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();
}

在程序中,如果只分析生产者是没有问题的,同样如果只分析消费者也是没有问题的。出现问题的原因就是生产者和消费者是并行执行的,并且共享一个仓库。两个线程之间没有任何的限制或约束。考虑一种情况,生产者在向仓库中放入产品的同时,消费者从仓库中取产品。相当于对共享资源同时读写,这肯定是不对的,也是不行的。

 

 

 临界资源(Critical Resource)

-每次只允许一个线程进行访问(读/写)的资源

-线程间的互斥(竞争)

-多个线程在同一时刻都需要访问临界资源

QMutex类是一把线程锁,保证线程间的互斥

-利用线程锁能够保证临界资源的安全性

QMutex中的关键成员函数

-void lock()

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

  当锁被获取,阻塞并等待锁释放

-void unlock()

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

QMutex使用示例

QMutex mutex;

mutex.lock();

//do something with critical resource

mutex.unlock();

注意:如果mutex在调用unlock()时处于空闲状态(即在调用lock函数之前就调用了unlock),那么程序的行为是未定的。所谓未定义就是什么时候产生bug,是不知道的。

解决生产者消费者问题:

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

static QString q_store;    //通过全局变量来模拟唯一的仓库
static QMutex mutex;

class Producer : public QThread
{
protected:
    void run()
    {
      int count = 0;
      while(true)
      {
          mutex.lock();

          //每次产生的数字在0-10之间,模拟了生产者将生产好的产品(一个数字)放入到仓库中(一个字符串类的对象)
          q_store.append(QString::number((count++) % 10));
          qDebug() << objectName() << " :" + q_store; //用字符串中字符表示当前仓库中的商品
          msleep(1);

          mutex.unlock();
      }
    }

};

class Customer : public QThread
{
protected:
    void run()
    {
        while(true)
        {
            mutex.lock();

            if(q_store != " ")
            {
                q_store.remove(0,1); //删除字符串中的第一个字符,表示取出一个商品
                qDebug() << objectName() << " : " + q_store;
            }
            msleep(1);

            mutex.unlock();
        }
    }
};

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();
}

原文地址:https://www.cnblogs.com/-glb/p/13381974.html