重温一下读写双缓冲问题
Posted xiaojack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重温一下读写双缓冲问题相关的知识,希望对你有一定的参考价值。
好久没写过双缓存了,趁现在有空重新温习下。
我们经常听说双缓存,但是很少使用多缓存,起码大多数情况下是这样吧。为什么不需要多缓冲呢,今天分析下。并不是缓冲区越多越好,这个需要考虑具体的应用场景。我们抽象假设一下应用场景,为了简化场景,假设只有一个读线程和一个写线程,设读时间为rt,写时间为wt,有三种情况:
1、当 rt==wt时,也就是说,读时间等于写时间。这时候,开辟几个缓冲区好呢,应该是两个。看以下时间图(图画得水,看得懂就好)
重上面的图可以看出,从写1开始,写1完成后,读1开始同时写2,当读1完成时写2正好也完成,因此理论上,这重情况下使用双缓存就可以了。
2、当rt>wt时,即读快于写,也就是读的时间小于写的时间,那么这时候应该使用几个缓存呢?理论上应该不超过两个,看以下时间图
写的时间比读的长,写1开始,写1完成后,读1开始时同时开始写2。当读1完成时,写2还没写完,所以这时候,即使有再多的缓存也没用(这里不考虑多线程写),所以最多有两个缓存就够了。为了搞高性能,这里最好使用多线程写,当然了,要是多核cpu。
3、当rt<wt时,即写快于读,这时候理论上应该设置2到3个缓存区就够了。看图
这个就不解释了,因为前面有,都类似,读得慢,写的再快也没有多大意义(除了占空间)。
有考虑不到的情景,请多多指教,谢谢!上个代码:代码里对_read_list和_write_list进行上锁操作,只是为了同时满足那三种时间关系。若已确定了是哪两种模型,可以去掉锁采用更快的方法
char buffer1[1024]; char buffer2[1024]; std::vector<char*> _buffer_list; std::vector<int> _read_list; // 可读缓存下标集合 std::vector<int> _write_list;// 可写缓存下标集合 std::mutex _mutex; // 同步锁 std::atomic<bool> _stopflag(false); // 全局停工标志 void thread_read(Event* _er,Event* _ew) { while(!_stopflag) { // 等待读 if (_er->wait_for(std::chrono::milliseconds(2000))) { while(true) { // 检查可读缓存的下标集合 int idx = -1; _mutex.lock(); if (!_read_list.empty()) { idx = *_read_list.begin(); _read_list.erase(_read_list.begin()); } _mutex.unlock(); if (idx==-1) { break; } // 进行写 char* pbuffer = _buffer_list[idx]; cout << pbuffer << endl; // 模拟读很慢 //Sleep(500); // 加入可写,上锁 _mutex.lock(); _write_list.push_back(idx); _mutex.unlock(); // 通知可写 _ew->notify_all(); } } // do other } } void thread_write(Event* _er,Event* _ew) { int global = 0; while(!_stopflag) { // 等待写 if (_ew->wait_for(std::chrono::milliseconds(2000))) { while(true) { // 检查可写缓存的下标集合 int idx = -1; _mutex.lock(); if (!_write_list.empty()) { idx = *_write_list.begin(); _write_list.erase(_write_list.begin()); } _mutex.unlock(); if (idx==-1) break; // 进行写 char* pbuffer = _buffer_list[idx]; memset(pbuffer,0,1024); sprintf(pbuffer, "this is threadid %i write %i buffer %i times", std::this_thread::get_id().hash(), idx, ++global); // 加入可读 _mutex.lock(); _read_list.push_back(idx); _mutex.unlock(); // 通知可读 _er->notify_all(); } } // do other } } int main() { _buffer_list.push_back(buffer1); _buffer_list.push_back(buffer2); Event event_read,event_write; std::list<std::thread> _list_thr; // 读线程 _list_thr.push_back(std::thread(thread_read,&event_read,&event_write)); // 写线程 _list_thr.push_back(std::thread(thread_write,&event_read,&event_write)); system("pause"); // 开始时,全部缓存可写 for (size_t i=0; i<_buffer_list.size(); ++i) _write_list.push_back(i); //通知写 event_write.notify_once(); system("pause"); _stopflag = true; for (auto& thr : _list_thr) thr.join(); return 0; }
以上是关于重温一下读写双缓冲问题的主要内容,如果未能解决你的问题,请参考以下文章