zoukankan      html  css  js  c++  java
  • 多线程间的互斥(上)

    值得思考的问题:

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

    生产消费者问题:
    -有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();
    }
    复制代码

  • 相关阅读:
    8088汇编跳转和PSW状态字寄存器
    Delphi的函数指针
    服务器系统及软件常见漏洞
    TGraphiControl响应WM_MOUSEMOVE的过程(以TPaintBox为例)good
    两个奇怪的取地址符号
    把x指针指向的4个字节次序颠倒过来
    DELPHI中的消息处理机制(三种消息处理方法的比较,如何截断消息)
    探索C++的底层机制
    setprecision、fixed、showpoint的用法总结(经典!!超经典!!)
    段寄存器和8种地址寻址方式
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14320676.html
Copyright © 2011-2022 走看看