信号量(Semaphore)是另一种限制对共享资源进行访问的线程同步机制,与互斥量(Mutex)相似,但有区别。
互斥量只能被锁定一次,信号量可以多次使用,信号量常用来保护一定数量的相同的资源。
QSemaphore是实现信号量功能的类,提供以下几个基本函数:
acquire(int n): 尝试获得n个资源,如果没有这么多资源,线程阻塞直到n个资源可用
release(int n): 释放n个资源,如果信号量资源已经被全部释放再release(),就可以创建更多的资源,增加可用数。
int available(): 放回当前信号量可用的资源数,不为负,若为0,表示没有可用资源
bool tryAcquire(int n=1): 尝试获取n个资源,不成功是不阻塞线程
以下是多个缓冲区示例:
const int BufferSize = 10;
int buffer1[BufferSize];
int buffer2[BufferSize];
int buffer3[BufferSize];
int crtBuf = 1;//当前缓冲区序号
int tempBuf = 1;
quint8 Data = 0;//数据流
QSemaphore emptyBufs(3);
QSemaphore fullBufs;
QThreadWrite::QThreadWrite(QObject* parent)
: QThread(parent)
{
m_gonOn = false;
}
QThreadWrite::~QThreadWrite() {
}
void QThreadWrite::stopThread() {
m_gonOn = false;
}
void QThreadWrite::run() {
m_gonOn = true;
crtBuf = 1;
tempBuf = 1;
Data = 0;
int av = emptyBufs.available();
if (av < 3)
emptyBufs.release(3 - av);
while (m_gonOn) {
emptyBufs.acquire(); //获取一个空的缓冲区
for (int i = 0; i < BufferSize; i++) {
if (crtBuf == 1) {
buffer1[i] = Data;
}
else if (crtBuf == 2) {
buffer2[i] = Data;
}
else {
buffer3[i] = Data;
}
Data++;
msleep(30);
}
tempBuf = crtBuf;
if (crtBuf == 1) {
crtBuf = 2;
}
else if (crtBuf == 2) {
crtBuf = 3;
}
else {
crtBuf = 1;
}
fullBufs.release();//释放一个满的缓冲区
}
}
QThreadRead::QThreadRead(QObject* parent)
: QThread(parent)
{
m_gonOn = false;
}
QThreadRead::~QThreadRead() {
}
void QThreadRead::stopThread() {
m_gonOn = false;
}
void QThreadRead::run() {
m_gonOn = true;
int av = fullBufs.available();
if (av > 0)
fullBufs.acquire(av);//将fullbufs可用资源个数初始化为0
while (m_gonOn) {
fullBufs.acquire();//等待缓冲区满
int bufferData[BufferSize];
if (crtBuf == 1) {
for (int i = 0; i < BufferSize; i++)
bufferData[i] = buffer1[i];
}
else if (crtBuf == 2) {
for (int i = 0; i < BufferSize; i++) {
bufferData[i] = buffer2[i];
}
}
else {
for (int i = 0; i < BufferSize; i++) {
bufferData[i] = buffer3[i];
}
}
emptyBufs.release();//释放一个空缓冲区
emit returnValueSignal(bufferData, BufferSize, tempBuf);
}
}
主线程测试代码:
void QSemaphorePro::returnValueSlot(int* buffer, int size, int num) {
QString str = QString::asprintf("第%d个缓冲区: ",num);
for (int i = 0; i < size; i++) {
str = str + QString::asprintf("%d, ", *buffer);
buffer++;
}
str = str + "\n";
ui.plainTextEdit->appendPlainText(str);
}
void QSemaphorePro::on_startThreadBtn_clicked() {
if (!m_read->isRunning()) {
m_read->start();
}
if (!m_write->isRunning()) {
m_write->start();
}
ui.stopThreadBtn->setEnabled(true);
ui.startThreadBtn->setEnabled(false);
}
void QSemaphorePro::on_stopThreadBtn_clicked() {
if (m_read->isRunning()) {
m_read->stopThread();
m_read->terminate();//必须使用terminate(),防止两个线程之间有互锁关系无法结束线程。
m_read->wait();
}
if (m_write->isRunning()) {
m_write->stopThread();
m_write->terminate();
m_write->wait();
}
ui.stopThreadBtn->setEnabled(false);
ui.startThreadBtn->setEnabled(true);
}
void QSemaphorePro::on_clearBtn_clicked() {
ui.plainTextEdit->clear();
}
动态演示为: