基于信号量的线程同步

	信号量(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();
}

动态演示为:
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值