[英]Lock free atomic circular queue not working properly
我試圖創建一個無鎖的原子循環隊列,但無法正常工作。
我創建了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;
}
您需要了解的第一件事是單核單線程處理器上的多線程。 如果運行以上代碼的處理器是單核單線程處理器,則不會有並行運行的線程。 這種處理器上的多線程有點像多進程概念。 一次只運行一個線程,並且在一定時間段后,當第一個線程使用了其時間片時,操作系統將調度它進入睡眠狀態,另一個線程啟動並開始運行。 這就是為什么看到“ Pop線程在push線程完全運行之后運行,反之亦然”的原因。
實際上,@ MikeMB指出了根本原因,其原因是運行循環太短。 如果將陣列容量更改為100,000,並將pop線程和push線程的循環計數器i增加到1000或更多,您會看到pop和push將交替運行。 這已在我的帶有gcc4.9.2的vmware CentOS 6.4上進行了測試。
祝好運!
當我添加一些命令行選項進行編譯時,它可以正常工作。 感謝大家的建議。
我使用以下命令進行編譯。
g ++ -std = c ++ 11 -Full -Wall -pedantic -pthread -latomic main.cpp
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.