【发布时间】:2015-07-21 13:10:52
【问题描述】:
我尝试创建一个无锁原子循环队列,但它无法正常工作。
我创建了 2 个线程。一种用于推入队列,另一种用于从队列中弹出。但是;
问题: -当推送线程运行时,弹出线程没有机会运行。推送线程完全运行后,弹出线程运行,反之亦然。
我对 C++ 了解不多。那么,请您编辑我的代码以使其正常工作吗?
我使用的是 GCC 4.8.1
提前致谢。
代码:
#include <cstdlib>
#include <iostream>
#include <atomic>
#include <cstddef>
#include <thread>
#include <stdio.h>
#include <unistd.h>
#define capacity 1000
std::atomic<int> _head;
std::atomic<int> _tail;
int array[capacity];
int increment(int size)
{
return (size+1)%capacity;
}
bool push(int *item)
{
printf("Inside push\n");
const int current_tail= _tail.load(std::memory_order_relaxed);
const int next_tail=increment(current_tail);
if(next_tail != _head.load(std::memory_order_acquire))
{
array[current_tail]=*item;
_tail.store(next_tail,std::memory_order_release);
return true;
}
return false; //Queue is Full
}
bool pop(int *item)
{
printf("Inside pop\n");
const int current_head=_head.load(std::memory_order_relaxed);
if(current_head==_tail.load(std::memory_order_acquire))
{
return false;//empty queue
}
*item=array[current_head];
_head.store(increment(current_head),std::memory_order_release);
return true;
}
bool isEmpty()
{
return(_head.load()==_tail.load());
}
bool isFull()
{
const int next_tail=increment(_tail);
return (next_tail==_head.load());
}
bool isLockfree()
{
return (_tail.is_lock_free() && _head.is_lock_free());
}
void *threadfunction_push()
{
int item,i;
bool flag;
item=0;
for(i=0;i<10000;i++)
{
while(isFull())
std::this_thread::yield();
++item;
push(&item);
printf("pushed %d into queue\n",item);
//usleep(100);
}
}
void *threadfunction_pop()
{
int item,i;
item=0;
for(i=0;i<10000;i++)
{
while(isEmpty())
std::this_thread::yield();
pop(&item);
printf("popped %d from queue\n",item);
}
i=isLockfree();
if(i)
printf("Queue is lock Free");
}
int main(int argc, char** argv)
{
std::thread thread_push(threadfunction_push);
std::thread thread_pop(threadfunction_pop);
thread_push.join();
thread_pop.join();
return 0;
}
【问题讨论】:
-
您知道,这个队列只适用于单个生产者和单个消费者吗?原因,它们一个接一个地运行的原因可能是循环太短了。当第二个线程被创建并计划运行时,第一个线程可能已经完成了。
-
是的,这是单个生产者和单个消费者队列。我尝试增加循环计数器,但仍然无法正常工作。
-
多少?您是如何确定它不起作用的?
-
我尝试循环运行 100000 次,但前 100000 次仅运行 pop 线程,100000 次后 push 线程运行。我希望两个线程并行运行。
-
这不是多线程编程的工作方式。你有像
isEmpty这样无用的函数这一事实表明你需要更好地理解并发编程的基本思想,可能来自教科书。
标签: c++ multithreading c++11