Qt线程的同步和互斥

线程同步
例子:在三个线程中,分别计算[1, 300] ,[301, 600], [601, 1000]的和,最后再将三个和相加得出[1,1000]的和

#include <QtCore/QCoreApplication>
#include <QThread>
#include <QDebug>

/*
  sum(n) => 1 + 2 + 3 + ... + n

  sum(1000) => ?

            [1, 1000] =  [1, 300] [301, 600] [601, 1000]
  */

class Calculator : public QThread
{
protected:
    int m_begin;
    int m_end;
    int m_result;

    void run()
    {
        qDebug() << objectName() << ": run() begin";

        for(int i=m_begin; i<=m_end; i++)
        {
            m_result += i;

            msleep(10);
        }

        qDebug() << objectName() << ": run() end";
    }
public:
    Calculator(int begin, int end)
    {
        m_begin = begin;
        m_end = end;
        m_result = 0;
    }

    void work()
    {
        run();
    }

    int result()
    {
        return m_result;
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main begin";

    Calculator cal1(1, 300);
    Calculator cal2(301, 600);
    Calculator cal3(601, 1000);

    cal1.setObjectName("cal1");
    cal2.setObjectName("cal2");
    cal3.setObjectName("cal3");

    // cal1.work();
    // cal2.work();
    // cal3.work();

    cal1.start();
    cal2.start();
    cal3.start();

    cal1.wait();
    cal2.wait();
    cal3.wait();

    int result = cal1.result() + cal2.result() + cal3.result();

    qDebug() << "result = " << result;

    qDebug() << "main end";
    
    return a.exec();
}

线程互斥
类QSemaphore
类QSemaphore提供类一个常用的信号量计数类。可以对QSemaphore对象的信号量进行加减,当信号量不足(被减后小于0)时线程会阻塞通过信号量的操作,线程执行的顺序会被指定,从而实现同步。

常用成员函数:
QSemaphore::QSemaphore(int n=0); //构造函数
int QSemaphore::avilable(); //获取信号量的剩余数
void QSemaphore::release(int n=1); //添加信号量
void QSemaphore::acquire(int n=1); //减少信号量

下面是一个生产者消费者模型

#include <QtCore/QCoreApplication>
#include <QThread>
#include <QSemaphore>
#include <Qdebug>

const int SIZE = 5;
unsigned char g_buff[SIZE] = {0};
QSemaphore g_sem_free(SIZE);
QSemaphore g_sem_used(0);

class Producer : public QThread   //生产者
{
protected:
    void run()
    {
        while( true )
        {
            int value = qrand() % 256;
            g_sem_free.acquire();  // 减1  生产者要生产一个,容量减1,检验其中是否还有容量
            for(int i=0; i<SIZE; i++)
            {
                if( !g_buff[i] )
                {
                    g_buff[i] = value;
                    qDebug() << objectName() << " generate: {" << i << ", " << value << "}";
                    break;
                }
            }
            g_sem_used.release();  //加1,生产者生产了一个加一
            sleep(2);
        }
    }
};

class Customer : public QThread      // 消费者
{
protected:
    void run()
    {
        while( true )
        {
            g_sem_used.acquire();  // 消费者消费了一个,减一
            for(int i=0; i<SIZE; i++)
            {
                if( g_buff[i] )
                {
                    int value = g_buff[i];
                    g_buff[i] = 0;
                    qDebug() << objectName() << " consume: {" << i << ", " << value << "}";
                    break;
                }
            }
            g_sem_free.release();  // 消费者消费了一个,容量加1
            sleep(1);
        }
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Producer p1;
    Producer p2;
    Producer p3;

    p1.setObjectName("p1");
    p2.setObjectName("p2");
    p3.setObjectName("p3");

    Customer c1;
    Customer c2;

    c1.setObjectName("c1");
    c2.setObjectName("c2");

    p1.start();
    p2.start();
    p3.start();

    c1.start();
    c2.start();
    
    return a.exec();
}

类QMutex
类QMutex用于保护一段代码在同一时刻只有一个线程可以执行。对QMutex对象可以进行上锁和解锁的操作。当某线程对QMutex对象上锁后,其他线程在对QMutex对象上锁时,线程会阻塞,直到QMutex对象被解锁。
使用QMutex可有实现线程间的互斥。

#include <QtCore/QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QDebug>

QMutex g_mutex_1;
QMutex g_mutex_2;

class ThreadA : public QThread
{
protected:
    void run()
    {
        while( true )
        {
            g_mutex_1.lock();
            qDebug() << objectName() << "get m1";
            g_mutex_2.lock();
            qDebug() << objectName() << "get m2";
            qDebug() << objectName() << "do work ...";
            g_mutex_2.unlock();
            g_mutex_1.unlock();

            sleep(1);
        }
    }
};

class ThreadB : public QThread
{
protected:
    void run()
    {
        while( true )
        {
            g_mutex_1.lock();
            qDebug() << objectName() << "get m2";
            g_mutex_2.lock();
            qDebug() << objectName() << "get m1";
            qDebug() << objectName() << "do work ...";
            g_mutex_2.unlock();
            g_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();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值