Multithreading Boost_lockFree_SPSC_队列是否真的大小可变且无数据丢失?
您好,我计划使用BoostSPSC队列。我必须有一个监听器,它总是监听传入的消息,一旦它收到消息,它会将消息放入队列,然后返回等待新消息。还有一个消费者从队列中弹出消息并对其进行处理 因为我不想让我的侦听器等待将锁写入队列,所以我更喜欢Multithreading Boost_lockFree_SPSC_队列是否真的大小可变且无数据丢失?,multithreading,c++11,boost,blockingqueue,Multithreading,C++11,Boost,Blockingqueue,您好,我计划使用BoostSPSC队列。我必须有一个监听器,它总是监听传入的消息,一旦它收到消息,它会将消息放入队列,然后返回等待新消息。还有一个消费者从队列中弹出消息并对其进行处理 因为我不想让我的侦听器等待将锁写入队列,所以我更喜欢boost\u lockfree\u spsc\u queue。我相信,如果在初始化队列时设置fixed\u size,队列的大小会有所不同。但事实似乎并非如此 以下是我的代码: boost::lockfree::spsc_queue<int, boost:
boost\u lockfree\u spsc\u queue
。我相信,如果在初始化队列时设置fixed\u size
,队列的大小会有所不同。但事实似乎并非如此
以下是我的代码:
boost::lockfree::spsc_queue<int, boost::lockfree::fixed_sized<false>> lockFreeQ{10};
void sharedQueue::lockFreeProduce()
{
for(int i = 0; i < 100; i++)
{
lockFreeQ.push(i);
cout<<"--"<<i<<endl;
}
}
void sharedQueue::lockFreeConsume(){
for(int i = 0; i <100; i++){
/* Implement a blocking pop to the queue in order to waste cpu time by busy waiting*/
while(!(lockFreeQ.read_available() > 0))
{
//std::this_thread::yield();
std::this_thread::sleep_for(std::chrono::nanoseconds(10));
}
cout<<" ***"<<lockFreeQ.front()<<endl;
lockFreeQ.pop();
}
}
void sharedQueue:: TestLockFreeQueue()
{
std::thread t1([this]() { this->lockFreeProduce(); });
std::thread t2([this]() { this->lockFreeConsume(); });
t1.join();
t2.join();
}
如果大小可变,则应扩展队列的大小,并且不应丢失数据。它似乎覆盖了所解释的数据。在这种情况下,如何在不丢失数据的情况下处理此问题
谢谢将评论翻译成答案 该策略在
spsc_队列
中的工作方式如下:
typedef typename mpl::if_c<runtime_sized,
runtime_sized_ringbuffer<T, allocator>,
compile_time_sized_ringbuffer<T, capacity>
>::type ringbuffer_type;
如果您真的需要一个无锁列表数据结构,您应该通过将注释翻译成答案来查看著名的无锁列表数据结构 该策略在
spsc_队列
中的工作方式如下:
typedef typename mpl::if_c<runtime_sized,
runtime_sized_ringbuffer<T, allocator>,
compile_time_sized_ringbuffer<T, capacity>
>::type ringbuffer_type;
如果您确实需要一个无锁列表数据结构,您应该看看著名的无锁列表数据结构,您的队列仍然是一个循环缓冲区,最大大小为10。该策略唯一改变的是,它将使用动态分配的数组,而不是使用堆栈数组。您所说的“动态分配的数组”是什么意思?这是否意味着当队列已满时,数组的大小将增加?我的意思是数组将通过使用分配器进行分配。动态分配数组的大小将是您在构造函数中传递的大小。队列已满时,数组大小不会增加,相反,它将重写第一个索引上的数据,因为所使用的数据结构始终是一个循环缓冲区,大小与您在构造函数中传递的大小相同。因此,总结一下,在构造队列时,必须选择足够高的值,以确保在最佳情况下不会覆盖数据。基本上,使用循环队列无法保证这种行为,因为您永远不知道消费者何时会崩溃或开始缓慢处理。您的队列仍然是一个循环缓冲区,最大大小为10。该策略唯一改变的是,它将使用动态分配的数组,而不是使用堆栈数组。您所说的“动态分配的数组”是什么意思?这是否意味着当队列已满时,数组的大小将增加?我的意思是数组将通过使用分配器进行分配。动态分配数组的大小将是您在构造函数中传递的大小。队列已满时,数组大小不会增加,相反,它将重写第一个索引上的数据,因为所使用的数据结构始终是一个循环缓冲区,大小与您在构造函数中传递的大小相同。因此,总结一下,在构造队列时,必须选择足够高的值,以确保在最佳情况下不会覆盖数据。基本上,您无法使用循环队列来保证这种行为,因为您永远不知道消费者何时会崩溃或开始缓慢处理。
static size_t next_index(size_t arg, size_t max_size)
{
size_t ret = arg + 1;
while (unlikely(ret >= max_size))
ret -= max_size;
return ret;
}