忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT HPC论坛 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
楼主: zylthinking

[算法] 多线程读写无锁链表: 之前有没有相同的实现? (更新) [复制链接]

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-04-13 10:00 |显示全部楼层
本帖最后由 zylthinking 于 2017-04-13 10:01 编辑

回复 50# wlmqgzm

问题是在不分组映射的情况下, 我的在 多写一读 情况下是 wait_free 的, 甚至在一定意义上来说, 我的是多读多写情况下的 wait free;  这都是不需要分组的.并不是我只说是 lock free 的, 就一定意味着仅仅是 lock free 的

而你说的却是 单读单写 情况下的 wait_free, 然后分成多个组来减少碰撞;用这个能说明什么呢






论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2017-04-13 21:04 |显示全部楼层
本帖最后由 wlmqgzm 于 2017-04-13 21:15 编辑

回复 51# zylthinking

主要是觉得你这个库的思路是挺好的,但是不够方便, 也不是C++的,不够前沿,性能上也不好说,毕竟wait_free才是最快的,
可能我自己平时用的库更习惯吧, 给个范例,使用起来只需要定义好回调函数,不需要考虑线程等等复杂的东西, 仅仅push数据就好,  其余全部是全自动执行的,适应任意对象的高性能数据处理
template<typename T>
class  Wait_free_mpsc_ios_queue
{
  public:
    //   下面 vt_sp_ios 是预先定义好的Boost库多线程任务队列容器,  ushort_ios_num_begin和 ushort_ios_num_end 指明了容器中多个生产者ios的范围, size_t_size_in是预分配的队列大小
    Wait_free_mpsc_ios_queue( const std::vector<std::shared_ptr<boost::asio::io_service> > &vt_sp_ios, const unsigned short ushort_ios_num_begin, const unsigned short ushort_ios_num_end, const size_t size_t_size_in );
   
    ~Wait_free_mpsc_ios_queue( void );

    // 定义下列一行,  只需要push数据, 然后消费者会自动处理数据,
    void   set_ios_and_function_pop( const std::shared_ptr<boost::asio::io_service>  &sp_ios_pop_in, const std::function<void(T&)>  &function_pop_in );
    //  定义下列一行, 当全部数据处理完毕后,消费者会自动调用function_after_pop_all_in
    void   set_function_after_pop_all( const std::function<void(void)>  &function_after_pop_all_in );

    //  当定义下列一项后,  生产者还会自动处理消费者返回的结果
    void   set_function_push_callback( const std::function<void(T&)>  &function_push_callback_in );

    bool   push_callback_empty( void ) const;  //  检查 全部 回调任务是否为空
    bool   push_callback_empty( unsigned short ushort_ios_num ) const;  //  检查 单个ios 回调任务是否为空

    bool  push( T& t_in, unsigned short ushort_ios_num );  //生产者执行
    void  push_util_success( T& t_in, unsigned short ushort_ios_num );

    bool   full( unsigned short ushort_ios_num ) const;
    bool   empty( void ) const;
    bool   empty( unsigned short ushort_ios_num ) const;
    size_t size( void ) const;     //  队列中等待处理的数据数量
    size_t capacity( void ) const;
    bool   is_lock_free( void ) const;

    void   set_bool_fast_quit( bool bool_fast_quit );   //  设置是否快速退出, 默认是必须等待队列空才析构
    unsigned long long  get_push_count( void ) const;   //  统计总共push进队列的数据总数

private:

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-04-17 10:10 |显示全部楼层
回复 52# wlmqgzm

C++的,不够前沿,性能上也不好说,毕竟wait_free才是最快的

这两句, 前一句就不说什么了; 我不前沿就不前沿呗

第二句你什么意思? 合着我一直说你推崇的那个只能在一个读一个写的情况下可以 wait free; 而我的自己认为多个写 一个读的情况下也是 wait free 压根就没看, 就闭眼睛重复念经了;

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2017-04-18 00:52 |显示全部楼层
本帖最后由 wlmqgzm 于 2017-04-18 01:46 编辑

要么楼主测试一下性能吧,  跟boost lockfree_spsc_queue可以对比测试一下, 那个是wait_free的, 我自己测试过, 在主频3.2G的双核CPU下, 传送int整数,  测试每秒push进队列2亿条记录, pop出2亿条记录.
我们公司内部的wait_free_spsc_queue大约是:   传送int整数,  测试每秒push进队列3亿条记录, pop出3亿条记录.
既然楼主坚决认为自己是在实现wait_free, 建议也push/pop测试一下, 看有多强.

wait_free/lock_free 现在基本都已经形成套路了,  各大公司都有成熟的模型,  一般wait_free有要求, 就是push和pop互不干扰(必须要间隔超过64Byte, 否则会有false sharing问题, 一般有足够的空间和足够的数据量的话, 不会有此问题)
其实, 我大概看了代码, 初步判断楼主的实现不是wait_free的,  
wait_free 的实现有严格的技术要求, 有很多类似 std::memory_order之类的很多东西, 还有很多的内存屏障,
在多数情况下, push代码所有访问的数据都是独立的, 不会被pop影响,
类似的pop也一样,
本来lock_free就够难实现的了, 更何况wait_free就更难了, 更难的是 多生产者 + 消费者  抢 一个队列, 还不能够有等待(wait), 我明明看到好多CAS spin在等待的(wait)
我目前还没有看到类似楼主这样的wait_free结构, 学识浅薄, 确实无法理解这种wait_free, ......

请务必测试一下性能, 看比标准版的wait_free快, 还是慢???   

论坛徽章:
12
水瓶座
日期:2014-06-10 09:51:0215-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摩羯座
日期:2014-07-21 10:11:2815-16赛季CBA联赛之八一
日期:2017-04-12 14:26:28
发表于 2017-04-18 07:07 |显示全部楼层
回复 54# wlmqgzm

这,xeon E5 2.20G,接近2亿,同一个Core上的两个Hyper-thread,不同Core也差不多,跨Numa的核就掉到一半了。抄这个论文的:《Single-Producer/ Single-Consumer Queues  on Shared Cache Multi-Core Systems

  1. #include <cstddef>
  2. #include <atomic>

  3. template <typename T, int capacity> class spsc_queue {
  4.   public:
  5.     spsc_queue(const T &val) : head(0), tail(0), invalid_val(val) {
  6.         for (int i = 0; i < capacity; i++) {
  7.             buf[i] = invalid_val;
  8.         }
  9.     }
  10.     spsc_queue(const spsc_queue &) = delete;
  11.     spsc_queue &operator=(const spsc_queue &) = delete;

  12.     bool enqueue(const T &data) {
  13.         if (buf[tail].load(std::memory_order_acquire) == invalid_val) {
  14.             buf[tail].store(data, std::memory_order_release);
  15.             tail = (tail + 1) % capacity;
  16.             return true;
  17.         }
  18.         return false;
  19.     }

  20.     bool dequeue(T &data) {
  21.         if (buf[head].load(std::memory_order_acquire) != invalid_val) {
  22.             data = buf[head].load(std::memory_order_relaxed);
  23.             buf[head].store(invalid_val, std::memory_order_release);
  24.             head = (head + 1) % capacity;
  25.             return true;
  26.         }
  27.         return false;
  28.     }

  29.   private:
  30.     static constexpr size_t CACHELINE = 64;

  31.     alignas(CACHELINE) unsigned int head;
  32.     alignas(CACHELINE) unsigned int tail;

  33.     char padding[CACHELINE - sizeof(tail)];

  34.     std::atomic<T> buf[capacity];
  35.     T invalid_val;
  36. };
复制代码




论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-04-18 11:49 |显示全部楼层
本帖最后由 zylthinking 于 2017-04-18 12:04 编辑
wlmqgzm 发表于 2017-04-18 00:52
要么楼主测试一下性能吧,  跟boost lockfree_spsc_queue可以对比测试一下, 那个是wait_free的, 我自己测试 ...

上边是你推崇的 boost , 下边是我的 lkf; 测试的是 1读1写的; 你自己看结果, 单线程下是我的占优势;
多线程下, 发现 boost 这玩意居然不是线程安全的, 我说的线程安全意思是多个读多个写, 它文档中的线程安全很可能是一个读一个写彼此安全 。
多线程下看时间是它占点优势, 但不大; 但考虑到它结果都是错的, 你自己明白是什么意思boost 是 apt install 下载的, 优化选项可能没有优化到最好,  姑且存疑


单线程 boost:
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 17, read 17, nr = 0
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 13, read 13, nr = 0
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 14, read 14, nr = 0
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 12, read 12, nr = 0

单线程 lkf:
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 11, read 11, nr = 0
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 12, read 12, nr = 0
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 11, read 11, nr = 0
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
1 writer, 1 reader, nr = 100000
write 8, read 8, nr = 0



boost多线程 50 读, 2个写, 只看速度, 不管数据正确性

zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 243, read 311
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 248, read 176
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 250, read 305
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 252, read 298
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 246, read 279

boost多线程 500 读, 2个写, 只看速度, 不管数据正确性

zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2404, read 2475
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2477, read 2554
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2520, read 2328
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2474, read 2508
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2508, read 2528



lkf多线程 50 读, 2个写, 只看速度, 最终数据是正确的


zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 305, read 343
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 355, read 356
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 292, read 388
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 323, read 364
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
50 writer, 2 reader, nr = 5000000
write 316, read 373


lkf多线程 500 读, 2个写, 只看速度, 最终数据是正确的

zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2672, read 3622
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2589, read 3986
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2664, read 3614
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2709, read 3611
zylthinking@linux:~$ g++ c.cpp now.c -lpthread; ./a.out
run = 0
500 writer, 2 reader, nr = 50000000
write 2638, read 3717





论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-04-18 11:51 |显示全部楼层
zylthinking 发表于 2017-04-18 11:49
上边是你推崇的 boost , 下边是我的 lkf; 测试的是 1读1写的; 你自己看结果, 单线程下是我的占优势;  ...

测试代码:


  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <pthread.h>
  5. #include <boost/lockfree/spsc_queue.hpp>

  6. #include "lkf.h"
  7. static LKF_LIST(list);

  8. #define nrp 100000
  9. #define nrt 1
  10. uint32_t now();

  11. #define uselkf 0
  12. int nnnnn = 0;
  13. struct lkf_node** node_array = NULL;

  14. static int run = 0;
  15. static struct lkf_node* pool = NULL;
  16. static int indx = 0;
  17. static int nr = 0;
  18. static uint32_t t1;

  19. boost::lockfree::spsc_queue<lkf_node*, boost::lockfree::capacity<50000000> ,
  20.                              boost::lockfree::fixed_sized<true> > spsc_queue;
  21. void* writer(void* any)
  22. {
  23.     int* intp = (int *) any;
  24.     while (run == 0) {
  25.         usleep(100);
  26.     }
  27. #if uselkf
  28.     for (int i = 0; i < nrp; ++i) {
  29.         int idx = __sync_fetch_and_add(&indx, 1);
  30.         struct lkf_node* nodep = &pool[idx];
  31.         lkf_node_put(&list, nodep);
  32.     }
  33. #else
  34.     for (int i = 0; i < nrp; ++i) {
  35.         int idx = __sync_fetch_and_add(&indx, 1);
  36.         struct lkf_node* nodep = &pool[idx];
  37.         spsc_queue.push(nodep);
  38.     }
  39. #endif

  40.     __sync_sub_and_fetch(&run, 1);
  41.     intp[0] = (int) (now() - t1);
  42.     return NULL;
  43. }

  44. void* reader(void* any)
  45. {
  46.     int* intp = (int *) any;
  47.     while (run == 0) {
  48.         usleep(100);
  49.     }
  50. #if uselkf
  51.     while (nr > 0) {
  52.         struct lkf_node* nodep = lkf_node_get(&list);
  53.         if (nodep == NULL) {
  54.             continue;
  55.         }

  56.         __sync_sub_and_fetch(&nr, 1);
  57.         struct lkf_node* cur = NULL;
  58.         do {
  59.             cur = lkf_node_next(nodep);
  60.             if (cur == nodep) {
  61.                 break;
  62.             }

  63.             if (cur != NULL) {
  64.                 __sync_sub_and_fetch(&nr, 1);
  65.             }
  66.         } while (1);
  67.     }
  68. #else
  69.     while (nr > 0) {
  70.         int n = (int) spsc_queue.pop(node_array, nnnnn);
  71.         __sync_sub_and_fetch(&nr, n);
  72.     }
  73. #endif
  74.     intp[0] = (int) (now() - t1);
  75.     return NULL;
  76. }

  77. int main(int argc, char** argv)
  78. {
  79.     int n = 0;
  80.     int used1[1024] = {0};
  81.     for (int i = 0; i < nrt; ++i) {
  82.         pthread_t tid;
  83.         if(0 == pthread_create(&tid, NULL, writer, &used1[i])) {
  84.             ++n;
  85.             pthread_detach(tid);
  86.         }
  87.     }

  88.     nr = nrp * n;
  89. #if !uselkf
  90.     nnnnn = nr;
  91.     node_array = (struct lkf_node**) malloc(sizeof(struct lkf_node*) * nr);
  92.     if (node_array == 0) {
  93.         printf("memory\n");
  94.         return 0;
  95.     }
  96. #endif

  97.     pool = (struct lkf_node *) malloc(sizeof(struct lkf_node) * nr);
  98.     if (pool == 0) {
  99.         printf("memory\n");
  100.         return 0;
  101.     }

  102.     int readers = 0;
  103.     int used2[1024] = {0};
  104.     for (int i = 0; i < 1; ++i) {
  105.         pthread_t tid;
  106.         if(0 == pthread_create(&tid, NULL, reader, &used2[i])) {
  107.             ++readers;
  108.             pthread_detach(tid);
  109.         }
  110.     }

  111.     printf("run = %d\n", run);
  112.     printf("%d writer, %d reader, nr = %d\n", n, readers, nr);

  113.     t1 = now();
  114.     run = n;

  115.     sleep(10);
  116.     int max1 = 0, max2 = 0;
  117.     for (int i = 0; i < n; ++i) {
  118.         if (used1[i] > max1) {
  119.             max1 = used1[i];
  120.         }
  121.     }

  122.     for (int i = 0; i < readers; ++i) {
  123.         if (used2[i] > max2) {
  124.             max2 = used2[i];
  125.         }
  126.     }

  127.     printf("write %d, read %d, nr = %d\n", max1, max2, nr);
  128.     return 0;
  129. }
复制代码

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-04-18 11:58 |显示全部楼层
本帖最后由 zylthinking 于 2017-04-18 12:25 编辑
wlmqgzm 发表于 2017-04-18 00:52
要么楼主测试一下性能吧,  跟boost lockfree_spsc_queue可以对比测试一下, 那个是wait_free的, 我自己测试 ...
编辑掉, 不吵架

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:412015年辞旧岁徽章
日期:2015-03-03 16:54:15拜羊年徽章
日期:2015-03-03 16:15:432015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
发表于 2017-04-18 12:25 |显示全部楼层
第一次听到无锁读***写***队例, 就觉得很神奇。怎么可能无锁呢??????
想啊想, 还是觉得怎么可能无锁呢???

看了楼主的代码, 还是觉得, 怎么可能远锁呢????
lollol

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-04-18 12:30 |显示全部楼层
folklore 发表于 2017-04-18 12:25
第一次听到无锁读***写***队例, 就觉得很神奇。怎么可能无锁呢??????
想啊想, 还是觉得怎么可能无 ...



没有真正无锁的代码; 这前提下, 更多的人在意的是函数的名称中是否有 lock 或 wait 的字眼
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP