0
点赞
收藏
分享

微信扫一扫

EA&UML日拱一卒-多任务编程超入门-(12)关于Semaphore,一个不得不说的实例


每 一个成熟的开发工具,都会附带很多示例,用来说明工具本身和相关语言的用法。编程者往往会忽略这些例子而直奔自己的开发目标。基本上这也不是什么大问题, 因为那些例子大多很简单,用的时候看一下就行了。但是Qt中关于Semaphore的实例,却是无论如何都不应该忽略的。


代码说明


全局变量


//数据量
const int DataSize = 100000;
//缓冲区大小
const int BufferSize = 8192;
//缓冲区
char buffer[BufferSize];
//缓冲区空闲空间Semaphore
QSemaphore freeBytes(BufferSize);
//缓冲区数据Semaphore
QSemaphore usedBytes;


写数据线程


class Producer : public QThread
{
public:
void run() override
{
for (int i = 0; i < DataSize; ++i) {
freeBytes.acquire();
buffer[i % BufferSize]
= "ACGT"[(int)qrand() % 4];
usedBytes.release();
}
}
};


首先略过两个Semaphore来读程序。run方法向缓冲区中写入数据。由于buffer的下标为i % BufferSize,所以这是一个循环队列。

接 下来看两个Semaphore的用法。freeBytes是空闲领域关联的Semaphore,只要循环队列中有空闲空间,acquire就会顺利通过, 否则写数据线程在acquire方法处发生阻塞。当数据写入成功以后,调用usedBytes的release方法,增加usedBytes的计数值。


读数据线程


class Consumer : public QThread
{
public:
void run() override
{
for (int i = 0; i < DataSize; ++i) {
usedBytes.acquire();
fprintf(stderr, "%c",
buffer[i % BufferSize]);
freeBytes.release();
}
}
};


run 方法从循环队列中读数据。关键还是两个Semaphore的用法。usedBytes是数据领域关联的Semaphore,只用循环队列中有数 据,acquire就会顺利通过,否则读数据线程在acquire方法处发生阻塞。当数据读出成功以后,调用freeBytes的release方法,增 加freeBytes的计数值。


主程序


int main(int argc, char *argv[])
{
Producer producer;
Consumer consumer;
producer.start();
consumer.start();
producer.wait();
consumer.wait();
return 0;
}


主程序很简单,分别启动两个线程,然后就安静地等待两个线程结束。


稍微总结一下


  1. 这个实例的核心就是一个循环队列和两个Samphore
  2. 通过循环队列传递数据
  3. 通过两个Semaphore同时实现了数据的保护和两个线程之间的同步


思考题


  1. 如何设计一个类,将核心的部分包装起来以便将来使用?
  2. 有可能让这个类被更多的线程同时使用么?


写在文章的最后





本公共号的成长需要您的支持!


阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】



EA&UML日拱一卒-多任务编程超入门-(12)关于Semaphore,一个不得不说的实例_sed


举报

相关推荐

0 条评论