免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2743 | 回复: 8
打印 上一主题 下一主题

[其他] 请问这种lock-free list为什么enqueue冲突呢? [复制链接]

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-09-04 12:53 |只看该作者 |倒序浏览
本帖最后由 lxyscls 于 2016-11-03 17:55 编辑

dequeue没问题(没有释放内存)
enqueue冲突,但是没看出是什么原因
  1. #include <cstddef>
  2. #include <atomic>

  3. using namespace std;

  4. template <typename T>
  5. class queue;

  6. template <typename T>
  7. class record {
  8.     friend class queue<T>;
  9.     public:
  10.         record() : next(NULL) {}
  11.         record(const T &t) : value(t), next(NULL) {}

  12.     private:
  13.         T       value;
  14.         record  *next;
  15. };

  16. template <typename T>
  17. class queue {
  18.     public:
  19.         queue();

  20.         void enqueue(const T &t);
  21.         const T &dequeue(void);

  22.     private:
  23.         atomic<record<T> *>head;
  24.         atomic<record<T> *>tail;
  25. };

  26. template <typename T>
  27. queue<T>::queue()
  28. {
  29.     record<T> *q = new record<T>;

  30.     head.store(q);
  31.     tail.store(q);
  32. }

  33. template <typename T>
  34. void queue<T>::enqueue(const T &t)
  35. {
  36.     record<T> *q = new record<T>(t);
  37.     record<T> *p = tail.load();
  38.         
  39.     do {                                                                                                                                                                                       
  40.         p->next = q;
  41.     } while (!tail.compare_exchange_weak(p, q));
  42. }

  43. template <typename T>
  44. const T &queue<T>::dequeue(void)
  45. {
  46.     record<T> *p = head.load();

  47.     do {
  48.         if (p->next == NULL)
  49.             return static_cast<T>(-1);
  50.     } while (!head.compare_exchange_weak(p, p->next));

  51.     return p->next->value;
  52. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2015-09-04 14:21 |只看该作者
enqueue 有问题,51行的 p->next = q; 没有保护,并行操作会导致p->next的值有问题

这里面涉及到两步操作(p->next的赋值,以及tail移到下一个节点的赋值),需要很好的进行设计,
核心的一点在于 tail->next 只有在NULL的时候才能更改,compare_exchange_weak要针对这个来使用,

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2015-09-04 19:36 |只看该作者
本帖最后由 lxyscls 于 2015-09-04 19:37 编辑

enqueue 有问题,51行的 p->next = q; 没有保护,并行操作会导致p->next的值有问题


<-- 请问这个时候会出现什么问题呢?假设两个线程同时enqueue,并同时拿到了同样的p,挂了不同的q(p->next = q)
      compare_exchange_weak不是只能有一个能成功吗?如果第一个线程成功了,那么第二个线程就不满足tail == p了,compare_exchange_weak应该失败才对

核心的一点在于 tail->next 只有在NULL的时候才能更改,compare_exchange_weak要针对这个来使用


<-- 关于这点,“酷壳”上面的实现,跟您讲得是一样的,但是因为C++ 11的<atomic>没办法对tail->next做compare_exchange_weak,atomic_compare_exchange_weak(tail->next, NULL, q)直接编译失败了
     atomic<record <T> *>tail并没有“next”这个成员,所以我才改成了1楼的方法,没料到错就错在这儿了

     能不能再详细指点指点,lock-free和C++都是新手

论坛徽章:
0
4 [报告]
发表于 2015-09-06 09:26 |只看该作者
http://www.codeproject.com/Artic ... entation-in-C-and-C

Lockfreeq.zip

6.22 KB, 下载次数: 4

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2015-09-06 09:44 |只看该作者
本帖最后由 lxyscls 于 2015-09-06 09:54 编辑

回复 4# wenlq


    谢谢!

    扫了一眼,是win32 API的,看来只能参考思路了

论坛徽章:
0
6 [报告]
发表于 2015-09-06 10:09 |只看该作者
本帖最后由 wenlq 于 2015-09-06 10:13 编辑

lockfree_linux.cpp (6.94 KB, 下载次数: 9)

[b

]回复 5# lxyscls


   

for linux

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2015-09-06 10:38 |只看该作者
回复 6# wenlq


    谢谢!这个思路跟前面那个一样,不过用了ASM来实现CAS,看来需要学习一下这个思路了

    其实我最想知道的是两个问题:为什么“p->next = q; CAS(tail, p, q);”不行,冲突在哪里?用c++ 11 <atomic>怎么改?

论坛徽章:
0
8 [报告]
发表于 2015-09-06 15:19 |只看该作者
错误2楼已经指出,多个enqueue会同时修改p->next的值,使得结果不定。
你需要对next使用atomic,需要定义其为atomic变量,正如head和tail所做的那样,虽然其实这个不是问题的核心。

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2015-09-06 16:49 |只看该作者
回复 8# TiGEr.zZ


    谢谢!

   
错误2楼已经指出,多个enqueue会同时修改p->next的值,使得结果不定。

   
    step 1: a thread p->next = q_1;
    step 2: b thread p->next = q_2;
    step 3: a thread CAS(tail, p, q_1);
   
    这个时候(tail==p && tail->next==q_2),如果CAS(tail, p, q_1),那么就相当于linked_list断掉了,因为tail->next != q_1

    干

   
   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP