线程同步
例子:在三个线程中,分别计算[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();
}