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

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

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

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

定义了两把线程锁,显然是为了保护两个临界资源而定义的。在线程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();
}

 

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