EA&UML日拱一卒-多任务编程超入门-(12)关于Semaphore,一个不得不说的实例
         
                原创
        
    
    
                
             ©著作权归作者所有:来自51CTO博客作者大连木匠的原创作品,请联系作者获取转载授权,否则将追究法律责任        
            
                    
                
每 一个成熟的开发工具,都会附带很多示例,用来说明工具本身和相关语言的用法。编程者往往会忽略这些例子而直奔自己的开发目标。基本上这也不是什么大问题, 因为那些例子大多很简单,用的时候看一下就行了。但是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;
}
主程序很简单,分别启动两个线程,然后就安静地等待两个线程结束。
稍微总结一下
- 这个实例的核心就是一个循环队列和两个Samphore
- 通过循环队列传递数据
- 通过两个Semaphore同时实现了数据的保护和两个线程之间的同步
思考题
- 如何设计一个类,将核心的部分包装起来以便将来使用?
- 有可能让这个类被更多的线程同时使用么?
写在文章的最后
 
 本公共号的成长需要您的支持!
 
 阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】
 
 
