博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
boost1.53中的lock-free
阅读量:4451 次
发布时间:2019-06-07

本文共 6088 字,大约阅读时间需要 20 分钟。

  原始网站:

     前言

  Boost1.53版本中新增加了lock-free库,终于有这么一款官方的lock-free结构出来了。以前在做高性能服务器处理的时候自己费了不少精力去网上搜索代码测试,不仅浪费精力而且可靠性还不敢保证。当然在项目中我使用最多的还是one-one的circle-buffer的方式,其实也就是boost::lockfree::spsc_queue,lock-free结构减少了大量的系统调用,因此特定场合下提升的性能还是非常明显的。总而言之,Boost的lock-free库还是比较值得期待和学习的。

  Non-blocking数据结构不再依赖于locks和mutexes去保证线程的安全。同步的操作完全在user-space完成,不需要直接和操作系统交互。不再依赖于guards,non-blocking数据结构需要atomic operations,尤其是CPU执行中不被中断。并不是所有的硬件支持相同系列的 atomic instructions,硬件不支持的将会使用gurard来进行模拟,当然这已经失去了lock-free的优势。

     影响lock-free的三种情况:

      Atomic Operations: 硬件提供atomic操作,这时候将会用spinlocks进行模拟,则会导致操作被block。

      Memory Allocations:操作系统的内存分配不是lock-free的。因此没有办法去实现真正的dynamically-sized的数据结构。boost.lockfree使用memory pool去分配内部的nodes。如果memory pool耗尽,则新节点的内存需要向操作系统进行索取导致内存分配。但是对于boost.lockfree可以采用special call访问失败的方式来避免内存分配。见后续lock-free内存相关设置
  
Exception Handling:C++ exception处理没有任何保证其real-time处理的行为。因此我们不鼓励在excetion的处理中使用lock-free代码。

     Boost.lockfree实现了三种数据结构
     boost::lockfree::queue: a lock-free multi-produced/multi-consumer queue
     boost::lockfree::stack: a lock-free multi-produced/multi-consumer stack
     boost::lockfree::spsc_queue: a wait-free single-producer/single-consumer queue (commonly known as ringbuffer)
    
    lock-free内存相关设置:
  • , defaults to boost::lockfree::fixed_sized<false> Can be used to completely disable dynamic memory allocations during push in order to ensure lockfree behavior. If the data structure is configured as fixed-sized, the internal nodes are stored inside an array and they are addressed by array indexing. This limits the possible size of the queue to the number of elements that can be addressed by the index type (usually 2**16-2), but on platforms that lack double-width compare-and-exchange instructions, this is the best way to achieve lock-freedom.

  • , optional If this template argument is passed to the options, the size of the queue is set at compile-time. It this option implies fixed_sized<true>

  • , defaults to <std::allocator<void>> Specifies the allocator that is used for the internal freelist

         
Example
  
1 #include 
2 #include
3 #include
4 5 #include
6 7 boost::atomic_int producer_count(0); 8 boost::atomic_int consumer_count(0); 9 10 boost::lockfree::queue
queue(128);11 12 const int iterations = 10000000;13 const int producer_thread_count = 4;14 const int consumer_thread_count = 4;15 16 void producer(void)17 {18 for (int i = 0; i != iterations; ++i) {19 int value = ++producer_count;20 while (!queue.push(value))21 ;22 }23 }24 25 boost::atomic
done (false);26 void consumer(void)27 {28 int value;29 while (!done) {30 while (queue.pop(value))31 ++consumer_count;32 }33 34 while (queue.pop(value))35 ++consumer_count;36 }37 38 int main(int argc, char* argv[])39 {40 using namespace std;41 cout << "boost::lockfree::queue is ";42 if (!queue.is_lock_free())43 cout << "not ";44 cout << "lockfree" << endl;45 46 boost::thread_group producer_threads, consumer_threads;47 48 for (int i = 0; i != producer_thread_count; ++i)49 producer_threads.create_thread(producer);50 51 for (int i = 0; i != consumer_thread_count; ++i)52 consumer_threads.create_thread(consumer);53 54 producer_threads.join_all();55 done = true;56 57 consumer_threads.join_all();58 59 cout << "produced " << producer_count << " objects." << endl;60 cout << "consumed " << consumer_count << " objects." << endl;61 }
1 #include 
2 #include
3 #include
4 5 #include
6 7 boost::atomic_int producer_count(0); 8 boost::atomic_int consumer_count(0); 9 10 boost::lockfree::stack
stack(128);11 12 const int iterations = 1000000;13 const int producer_thread_count = 4;14 const int consumer_thread_count = 4;15 16 void producer(void)17 {18 for (int i = 0; i != iterations; ++i) {19 int value = ++producer_count;20 while (!stack.push(value))21 ;22 }23 }24 25 boost::atomic
done (false);26 27 void consumer(void)28 {29 int value;30 while (!done) {31 while (stack.pop(value))32 ++consumer_count;33 }34 35 while (stack.pop(value))36 ++consumer_count;37 }38 39 int main(int argc, char* argv[])40 {41 using namespace std;42 cout << "boost::lockfree::stack is ";43 if (!stack.is_lock_free())44 cout << "not ";45 cout << "lockfree" << endl;46 47 boost::thread_group producer_threads, consumer_threads;48 49 for (int i = 0; i != producer_thread_count; ++i)50 producer_threads.create_thread(producer);51 52 for (int i = 0; i != consumer_thread_count; ++i)53 consumer_threads.create_thread(consumer);54 55 producer_threads.join_all();56 done = true;57 58 consumer_threads.join_all();59 60 cout << "produced " << producer_count << " objects." << endl;61 cout << "consumed " << consumer_count << " objects." << endl;62 }
1 #include 
#include
2 #include
#include
int producer_count = 0; 3 boost::atomic_int consumer_count (0); 4 boost::lockfree::spsc_queue
> spsc_queue; 5 const int iterations = 10000000;void producer(void){ 6 for (int i = 0; i != iterations; ++i) { int value = ++producer_count; 7 while (!spsc_queue.push(value)) ; }} 8 boost::atomic
done (false);void consumer(void){ int value; 9 while (!done) { while (spsc_queue.pop(value))10 ++consumer_count; } while (spsc_queue.pop(value))11 ++consumer_count;}int main(int argc, char* argv[]){12 using namespace std; cout << "boost::lockfree::queue is ";13 if (!spsc_queue.is_lock_free()) cout << "not ";14 cout << "lockfree" << endl; boost::thread producer_thread(producer);15 boost::thread consumer_thread(consumer); producer_thread.join();16 done = true; consumer_thread.join();17 cout << "produced " << producer_count << " objects." << endl;18 cout << "consumed " << consumer_count << " objects." << endl;}

 

 

转载于:https://www.cnblogs.com/davad/archive/2013/03/31/2991590.html

你可能感兴趣的文章
设计模式学习笔记(总结篇:模式分类)
查看>>
TCP的三次握手/建立连接
查看>>
Python 教程阅读笔记(一):使用解释器
查看>>
运算符重载
查看>>
SDWebImage 新版接口使用方法
查看>>
DataTable导出为word,excel,html,csv,pdf,.txt
查看>>
android ListView详解
查看>>
软件工程 第一次作业
查看>>
Content Server HA搭建
查看>>
vue-textarea 自适应高度
查看>>
(2)数据结构——线性表(链表)实现
查看>>
[leetCode]Linked List Cycle I+II
查看>>
leetcode中的python学习
查看>>
sqlserver打开对象资源管理器管理的帮助文档的快捷键
查看>>
JBOSSAS 5.x/6.x 反序列化命令执行漏洞(CVE-2017-12149)
查看>>
Zookeeper zkui-zookeeper图形化管理工具
查看>>
java运行时内存分类
查看>>
为什么说 Git 比 SVN 更好
查看>>
1.基础数据类型的初识 字符串 bool 整型 if else elif
查看>>
【设计模式】4、原型模式
查看>>