• 多线程间的互斥-锁(下)


    问题:程序有多少临界资源?需要多少线程锁?

    临界资源是没有任何的限制

    一般性原则:每一个临界资源都需要一个线程锁进行保护(一 一对应)

    定义了两把线程锁,显然是为了保护两个临界资源而定义的。在线程A中需要两个临界资源才能保证工作,这两个临界资源对应的线程锁就是m1,m2。在线程B中也需要两个临界资源才能保证工作。单看线程A和线程B都是正确的,那么它们两个加在一起就是多线程程序吗?这是一个非常有趣的问题,有趣的地方在于它们获取线程锁的顺序是不一样的。接下来就进行研究 

    有趣的示例:

    复制代码
    #include <QCoreApplication>
    #include <QThread>
    #include <QDebug>
    #include <QMutex>
    
    QMutex q_mutex_1;
    QMutex q_mutex_2;
    
    class ThreadA : public QThread
    {
    protected:
        void run()
        {
            while(true)
            {
                q_mutex_1.lock();
    
                qDebug() << objectName() << "get m1";
    
                q_mutex_2.lock();
    
                qDebug() << objectName() << "get m2";
    
                qDebug() << objectName() << "do work....";
    
                q_mutex_2.unlock();
                q_mutex_1.unlock();
            }
    
        }
    };
    
    class ThreadB : public QThread
    {
    protected:
        void run()
        {
            while(true)
            {
                q_mutex_2.lock();
    
                qDebug() << objectName() << "get m2";
    
                q_mutex_1.lock();
    
                qDebug() << objectName() << "get m1";
    
                qDebug() << objectName() << "do work....";
    
                q_mutex_1.unlock();
                q_mutex_2.unlock();
            }
        }
    };
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        ThreadA ta;
        ThreadB tb;
    
        ta.setObjectName("ta");
        tb.setObjectName("tb");
    
        ta.start();
        tb.start();
        return a.exec();
    }
    复制代码

    打印结果1:(注意这个地方的打印结果是不确定的)

     上面已经分析过,线程A和线程B要想正确的执行,需要得到两把锁,m1和m2.。从打印结果看,线程A只得到了,锁m1,线程B得到了锁m2。当线程A在获得了锁m1后,再尝试获取第二把锁m2,但是此时锁m2被线程B得到了,线程A等待线程B释放m2,才能继续往下执行。然而,线程B等待线程A释放m1,才能继续向下运行。这两个线程都在互相等待,谁也不释放锁,这样就造成了无限的等待,造成了死锁。

    线程A和线程B获取线程锁的顺序是不一样的。 

    线程的死锁概念

    -线程间相互等待临界资源而造成彼此无法继续执行

    发生死锁的条件:

    -系统中存在多个临界资源且临界资源不可抢占

    -线程需要多个临界资源才能继续执行

     

     m1保护r1,m2保护r2,依次类推。

    复制代码
    QMutex q_mutex_1;
    QMutex q_mutex_2;
    
    class ThreadA : public QThread
    {
    protected:
        void run()
        {
            while(true)
            {
                q_mutex_1.lock();
    
                qDebug() << objectName() << "get m1";
    
                q_mutex_2.lock();
    
                qDebug() << objectName() << "get m2";
    
                qDebug() << objectName() << "do work....";
    
                q_mutex_2.unlock();
                q_mutex_1.unlock();
    
                sleep(1);
            }
    
        }
    };
    
    class ThreadB : public QThread
    {
    protected:
        void run()
        {
            while(true)
            {
                q_mutex_1.lock();
    
                qDebug() << objectName() << "get m1";
    
                q_mutex_2.lock();
    
                qDebug() << objectName() << "get m2";
    
                qDebug() << objectName() << "do work....";
    
                q_mutex_2.unlock();
                q_mutex_1.unlock();
    
                sleep(1);
            }
        }
    };
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        ThreadA ta;
        ThreadB tb;
    
        ta.setObjectName("ta");
        tb.setObjectName("tb");
    
        ta.start();
        tb.start();
        return a.exec();
    }
    复制代码
  • 相关阅读:
    补习系列(4)-springboot 参数校验详解
    华为鲁勇:5G+云+AI三大核心引擎将驱动广州数字经济发展
    selenium firefox
    徐翔之后新生代“敢死队”浮出水面:八年一万倍
    ActiveMQ讯息传送机制以及ACK机制
    一元线性回归分析及java实现
    jsoup -- xml文档解析
    HDU 1020 Encoding 字符串
    PHP缓存之文件缓存
    Eclipse PHPEclipse 配置
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14320685.html
Copyright © 2020-2023  润新知