多线程安全无锁队列,求鉴定

cnlm2 2010-12-17 02:08:13
这个是基于原子操作写的, 测试环境:win32 vc2008, 代码如下,求大侠鉴定!

queue.h

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <windows.h>


template<class QElmType>
struct qnode
{
struct qnode *next;
QElmType data;
};


template<class QElmType>
class queue
{

public:
queue()
{
m_front = new qnode<QElmType>;
m_front->next = 0;
m_rear = m_front;
}
~queue() {}

void destroy()
{
while (m_front)
{
m_rear = m_front->next;
delete m_front;
m_front = m_rear;
}
}

//将新的节点放入队列尾部
bool push(QElmType e)
{
//新建一个节点
struct qnode<QElmType> *p = new qnode<QElmType>;
if (!p)
return false;
p->next = 0;
while (1)
{
struct qnode<QElmType> *rear = m_rear;
rear->next = p;
rear->data = e;

//如果队列没有改变将p赋值给m_rear,否则继续循环
if (InterlockedCompareExchangePointer((volatile PVOID *)&m_rear,
p, rear) == rear)
break;
}
return true;
}

bool pop(QElmType *e)
{
while (1)
{
struct qnode<QElmType> *front = m_front;
if (front == m_rear)
return false;

//如果队列位置没有变将m_front指向下一个位置,否则继续循环
if(InterlockedCompareExchangePointer((volatile PVOID *)&m_front,
m_front->next, front) == front)
{
*e = front->data;
delete front;
return true;
}
}

return true;
}

private:

struct qnode<QElmType> *m_front, *m_rear;

};


#endif //__QUEUE_H__


测试代码

testqueue.cpp

#include "queue.h"
#include <iostream>

queue<int> g_q;


DWORD WINAPI thread1(LPVOID l)
{
int i = 0;
while (1)
{
if (i%2!=0)
g_q.push(i);
i++;
Sleep(100);
}
return 0;
}

DWORD WINAPI thread2(LPVOID l)
{
int i = 0;
while (1)
{
if (i%2==0)
g_q.push(i);
i++;
Sleep(200);
}
return 0;
}

DWORD WINAPI thread3(LPVOID l)
{
int i;
while (1)
{
if (g_q.pop(&i))
std::cout << i << std::endl;
else
std::cout << "can not pop" << std::endl;
Sleep(500);
}
return 0;
}


DWORD WINAPI thread4(LPVOID l)
{
int i;
while (1)
{
if (g_q.pop(&i))
std::cout << i << std::endl;
else
std::cout << "can not pop" << std::endl;
Sleep(200);
}
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h1 = CreateThread(0, 0, thread1, 0, 0, 0);
HANDLE h2 = CreateThread(0, 0, thread2, 0, 0, 0);
HANDLE h3 = CreateThread(0, 0, thread3, 0, 0, 0);
HANDLE h4 = CreateThread(0, 0, thread4, 0, 0, 0);

char ch;
while (1)
{
std::cin >> ch;
if (ch == 'q')
break;
}
g_q.destroy();
return 0;
}



...全文
537 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
dfasri 2011-10-20
  • 打赏
  • 举报
回复
既然你也是用CAS的操作, 还倒不如直接抄网上的 MS-Queue 来实现, 理论和实践都已经证明了. 并且还可以多读多写.
arong1234 2010-12-18
  • 打赏
  • 举报
回复
1。你这还是不安全的,每次检查时别的线程可能还没访问,但是在你检查后再操作前,可能就访问了,你不能保证完全排除这种情况

2。你这样做的效率并不高。锁虽然有些开销,但是incremental lock机制也有,你增加的额外检查开销也很大,综合算起来,你的效率可能还会低
cnlm2 2010-12-18
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 peige2008 的回复:]

引用 6 楼 cnlm2 的回复:
引用 5 楼 peige2008 的回复:

struct qnode<QElmType> *rear = m_rear;---1
rear->next = p;----2
rear->data = e;----3

A执行完3之后,B冲过来执行3,竞争A获得继续执行,node安插成功,不过好像node.data已经被修改了。




b冲过来……
[/Quote]
看出来了,谢谢。是我疏忽了
cnlm2 2010-12-18
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 arong1234 的回复:]

1。你这还是不安全的,每次检查时别的线程可能还没访问,但是在你检查后再操作前,可能就访问了,你不能保证完全排除这种情况

2。你这样做的效率并不高。锁虽然有些开销,但是incremental lock机制也有,你增加的额外检查开销也很大,综合算起来,你的效率可能还会低
[/Quote]

是的,我在思考这个方案可行性!
PG 2010-12-17
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cnlm2 的回复:]
引用 5 楼 peige2008 的回复:

struct qnode<QElmType> *rear = m_rear;---1
rear->next = p;----2
rear->data = e;----3

A执行完3之后,B冲过来执行3,竞争A获得继续执行,node安插成功,不过好像node.data已经被修改了。


b冲过来执行3,a就获得不了啊,Interloc……
[/Quote]

看来您还没看出来,InterlockedCompareExchangePointer只保证他执行的 操作以原子方式,,当然你比较的是指针,指针里面的内容在InterlockedCompareExchangePointer之前被修改了您怎么办,!
zhengjiankang 2010-12-17
  • 打赏
  • 举报
回复
给楼主一个问题回去想想
所谓的无锁队列是为了提高效率的
如果效率低下锁不锁已经没有意义了

不知道对于你这个无锁队列
复制数据的开销会不会比锁的开销更大呢

如果节点数据是比较大的数据
人们需要的是共享数据也就是减少数据copy次数
您这样每次都要copy数据还能保证效率么
cnlm2 2010-12-17
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 peige2008 的回复:]

struct qnode<QElmType> *rear = m_rear;---1
rear->next = p;----2
rear->data = e;----3

A执行完3之后,B冲过来执行3,竞争A获得继续执行,node安插成功,不过好像node.data已经被修改了。
[/Quote]

b冲过来执行3,a就获得不了啊,InterlockedCompareExchangePointer函数会比较的,如果和原来一样才会安插
PG 2010-12-17
  • 打赏
  • 举报
回复
struct qnode<QElmType> *rear = m_rear;---1
rear->next = p;----2
rear->data = e;----3

A执行完3之后,B冲过来执行3,竞争A获得继续执行,node安插成功,不过好像node.data已经被修改了。
cnlm2 2010-12-17
  • 打赏
  • 举报
回复
难道帖子要沉了吗?
cnlm2 2010-12-17
  • 打赏
  • 举报
回复
欢迎高手们继续提出意见!
cnlm2 2010-12-17
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 libinfei8848 的回复:]

主线程中没有看到等待其他线程结束的地方,其他的都不错,可以在考虑别的同步对象
[/Quote]

谢谢回复。我再看看
libinfei8848 2010-12-17
  • 打赏
  • 举报
回复
主线程中没有看到等待其他线程结束的地方,其他的都不错,可以在考虑别的同步对象

64,642

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧