単純なC++高同時セキュリティキュー
4186 ワード
通常のデュアルロックキューは、ヘッダとテールが同時にあるか(すなわち、キューが空であるかどうか)を判断すると、ヘッダロックとテールロックのどちらが追加されるかを判断します.幸いなことに、賢い人は96年にもっと素晴らしいアルゴリズムを思いついた.このアルゴリズムもheadとtailの2つのロックを使用していますが、キューが初期化されたときにheadとtailポインタが空ではなく、空のノードを指す重要な点があります.enqueueの場合はキューの末尾に新しいノードを追加すればよい.Dequeueの場合、ヘッダノードではなくhead->next、すなわちヘッダノードの次のノードを返すのは少し複雑です.
このメソッドリファレンスhttp://www.parallellabs.com/2010/10/25/practical-concurrent-queue-algorithm/
以下は私の参考です.https://blog.csdn.net/mymodian9612/article/details/53608084?utm_source=blogxgwz1
変更された単純なC++(Linuxでも使用可能)高同時セキュリティキュー
家に帰った後、コードは思い出で変更されたので、間違いがあるかもしれません.大体そういう意味です.性能は私がテストしたもので、以前の普通の首尾ロックより10%から20%向上しました.
そうだtry_popを使うときに使う必要がありますが、
このメソッドリファレンスhttp://www.parallellabs.com/2010/10/25/practical-concurrent-queue-algorithm/
以下は私の参考です.https://blog.csdn.net/mymodian9612/article/details/53608084?utm_source=blogxgwz1
変更された単純なC++(Linuxでも使用可能)高同時セキュリティキュー
#ifndef __THREADSAFE_QUEUE2_H_
#define __THREADSAFE_QUEUE2_H_
#include
#include
#include
#include
template
class threadsafe_queue2
{
public:
threadsafe_queue2()
{
node *nd = new node();
nd->next = nullptr;
head = node;
tail = node;
}
threadsafe_queue2(const threadsafe_queue2&) = delete;
threadsafe_queue2 operator=(const threadsafe_queue2&) = delete;
~threadsafe_queue2() = default;
std::shared_ptr try_pop()
{
std::unique_lock<:mutex> ulkh(head_mut);
if(head.get()->next == nullptr)
return nullptr;
auto old_head = std::move(head);
head = std::move(old_head->next);
return head->data;
}
void push(T &&t)
{
std::shared_ptr new_data(std::make_shared(std::forward(t)));
std::unique_ptr new_tail(new node);
node *p = new_tail->get();
{
std::unique_lock<:mutex> ulkt(tail_mut);
p->data = new_data;
p->next = nullptr;
tail->next = std::move(new_tail);
tail = p;
}
data_cond.notify_one();
}
private:
struct node
{
std::shared_ptr data;
std::unique_ptr next;
};
std::mutex head_mut;
std::mutex tail_mut;
std::unique_ptr head;
node *tail;
std::condition_variable data_cond;
private:
node* get_tail()
{
std::unique_lock<:mutex> ulkt(tail_mut);
return tail;
}
};
template
class threadsafe_queue2
{
public:
threadsafe_queue2()
{
node *nd = new node();
nd->next = nullptr;
head = node;
tail = node;
}
threadsafe_queue2(const threadsafe_queue2&) = delete;
threadsafe_queue2 operator=(const threadsafe_queue2&) = delete;
~threadsafe_queue2()
{
node *pre;
for (; head->next != nullptr;)
{
pre = head;
head = head->next;
delete pre;
}
delete head;
}
T* try_pop()
{
node *old_head = nullptr;
{
std::unique_lock<:mutex> ulkh(head_mut);
if (head->next == nullptr)
return nullptr;
old_head = head;
head = head->next;
}
T *data = head->data;
delete old_head;
return data;
}
void push(T *t)
{
node *new_tail = new node;
{
std::unique_lock<:mutex> ulkt(tail_mut);
tail->data = t;
tail->next = new_tail;
tail = new_tail;
}
data_cond.notify_one();
}
private:
struct node
{
T *data;
node *next;
};
std::mutex head_mut;
std::mutex tail_mut;
node *head;
node *tail;
std::condition_variable data_cond;
private:
node* get_tail()
{
std::unique_lock<:mutex> ulkt(tail_mut);
return tail;
}
};
#endif
家に帰った後、コードは思い出で変更されたので、間違いがあるかもしれません.大体そういう意味です.性能は私がテストしたもので、以前の普通の首尾ロックより10%から20%向上しました.
そうだtry_popを使うときに使う必要がありますが、
std::shared_ptr data = xxx.try_pop();