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

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

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

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

    定义了两把线程锁,显然是为了保护两个临界资源而定义的。在线程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();
    }
    复制代码
  • 相关阅读:
    Matlab 绘制三维立体图(以地质异常体为例)
    Azure DevOps的variable group实现array和hashtable参数的传递
    Azure DevOps 利用rest api设置variable group
    Azure AADSTS7000215 其中一种问题的解决
    Power BI 实现实时更新Streaming Dataset
    AAD Service Principal获取azure user list (Microsoft Graph API)
    Matlab 沿三维任意方向切割CT图的仿真计算
    Azure Powershell script检测登陆并部署ARM Template
    Azure KeyVault设置策略和自动化添加secrets键值对
    Azure登陆的两种常见方式(user 和 service principal登陆)
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14320685.html
Copyright © 2011-2022 走看看