qq_38135573 2019-04-17 21:20 采纳率: 66.7%
浏览 603
已采纳

Linux死锁多线程编程在qt中运行异常

用ubuntu虚拟机写qt,在MainWindow类中写的好几个相关死锁代码总是异常中断,但把这部分代码单独提出写在一个cpp中就能编译通过并且正常输出

类里死锁代码部分
(简化了一下,只粘了最基本的一个死锁多线程)

//mainwindow.h

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    static void* Q2(void *arg);
    static void* P2(void *arg);
    void InitializedTable_unlock();
    void choose(int);

public slots:
    void unlock();

};

#endif // MAINWINDOW_H




//mainwindow.cpp




pthread_t tid[2];
// 静态初始化互斥量 
pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t mutexB = PTHREAD_MUTEX_INITIALIZER;

MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton_3_1_b,SIGNAL(clicked()),this,SLOT(unlock()));
}

MainWindow::~MainWindow()
{
    delete ui;
}


void* MainWindow::P1(void *arg) {
    MainWindow w;
    pthread_mutex_lock(&mutexA); 
    //P1 get mutexA
    //choose按钮对应移动函数
    w.choose(1);
    usleep(1000);
    pthread_mutex_lock(&mutexB);
    //P1 get mutexB
    w.choose(3);
    pthread_mutex_unlock(&mutexA);
    //P1 release mutexB
    w.choose(4);
    pthread_mutex_unlock(&mutexB); 
    //P1 release mutexA
    w.choose(5);
    return NULL;
}

void* MainWindow::Q1(void *arg) {
    MainWindow w;
    pthread_mutex_lock(&mutexB);
    //Q1 get mutexB
    w.choose(2);
    usleep(1000);
    pthread_mutex_lock(&mutexA);
    //Q1 get mutexA
    w.choose(6);
    pthread_mutex_unlock(&mutexB);
    //Q1 release mutexA
    w.choose(7);
    pthread_mutex_unlock(&mutexA);
    //Q1 release mutexB
    w.choose(8);
    return NULL;
}

void MainWindow::lock(void) {
    MainWindow m;

    // 创建线程 1
    pthread_create(&(tid[0]), NULL, m.Q1, NULL );
    // 创建线程 2 
    pthread_create(&(tid[1]), NULL, m.P1, NULL); 

    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

}

// 死锁资源按钮相应位移函数
void MainWindow::choose(int step){

    if(step == 1){
        //P1 get mutexA
        ......全都写的是对应的button进行位移的代码
    }
    else if(step == 2){
        //Q1 get mutexB
        ......
    }
    else if(step == 3){
        //P2 release mutexA
        ......
    }
    else if(step == 4){
        //P2 get mutexB
        ......
    }
    else if(step == 5){
        //P2 release mutexB
        ......
    }
    else if(step == 6){
        //Q2 get mutexA
        ......
    }
    else if(step == 7){
        //Q2 release mutexB
        ......
    }
    else if(step == 8){
        //Q2 release mutexA
        QPropertyAnimation *animation12 = new 
QPropertyAnimation(ui->pushButton_2_1_1,"geometry");
        animation12->setDuration(1000);
        animation12->setStartValue(QRect(110,280,141,71)); 
        animation12->setEndValue(QRect(110,140,141,71));
        animation12->start();
        QPropertyAnimation *animation13 = new 
QPropertyAnimation(ui->pushButton_2_1_1,"geometry");
        animation13->setDuration(1000);
        animation13->setStartValue(QRect(110,140,141,71)); 
        animation13->setEndValue(QRect(530,140,141,71));
        animation13->start();
    }
}

这部分代码运行不出来,不报错,但click一下那个unlock就异常中断

然后我把这部分代码单独整理成一个cpp就能跑

#include <QCoreApplication>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>  //用于sleep()


pthread_t tid[2];
// 静态初始化互斥量 
pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t mutexB = PTHREAD_MUTEX_INITIALIZER;

void* P1(void *arg) {

    pthread_mutex_lock(&mutexA); 
    printf("P1 get mutexA\n");
    usleep(1000);
    pthread_mutex_unlock(&mutexB); 
    printf("P1 release mutexA\n");
    pthread_mutex_lock(&mutexB); 
    printf("P1 get mutexB\n");
    pthread_mutex_unlock(&mutexA); 
    printf("P1 release mutexB\n");
    return NULL;
}

void* Q1(void *arg) {
    pthread_mutex_lock(&mutexB);
    printf("Q1 get mutexB\n");
    usleep(1000);
    pthread_mutex_lock(&mutexA);
    printf("Q1 get mutexA\n");
    pthread_mutex_unlock(&mutexB);
    printf("Q1 release mutexA\n");
    pthread_mutex_unlock(&mutexA);
    printf("Q1 release mutexB\n");
    return NULL;
}

int main() {

    // 创建线程 1
    pthread_create(&(tid[0]), NULL, &Q1, NULL );
    // 创建线程 2 
    pthread_create(&(tid[1]), NULL, &P1, NULL); 

    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

    return 0;
}

结果也是我想要的

P1 get mutexA
Q1 get mutexB
P1 release mutexA
P1 get mutexB
P1 release mutexB
Q1 get mutexA
Q1 release mutexA
Q1 release mutexB

  • 写回答

1条回答 默认 最新

  • qq_38135573 2019-04-17 21:21
    关注

    改成用qt自带的Qthread写多线程
    通过信号和槽实现线程进度与界面变化的同步

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 计算300m以内的LD衰减
  • ¥15 Lxml库中Xpath查找指定节点
  • ¥15 数据爬取,python
  • ¥15 怎么看 cst中一个面的功率分布图,请说明详细步骤。类似下图
  • ¥15 为什么我的pycharm无法用pyqt6的QtWebEngine
  • ¥15 FOR循环语句显示查询超过300S错误怎么办
  • ¥15 数电设计题 没有设计思路 不知道用什么芯片进行设计 求提供设计思路
  • ¥60 设计一种优化算法结合案例给出智能仓储四向穿梭车的调度计划
  • ¥15 Errno2:No such file or directory,在当前文件确实没有该图片,怎么解决?
  • ¥15 博世摄像头数据存储的问题(iscsi)