how to prevent corruption in concurrent lifo stack implemented with atomic compare and swap

天涯浪子 提交于 2019-12-05 13:10:30

(I am discarding my previous answer.)

The issue is that you do not have a mechanism to atomically read gHead and gHead->next, but such is needed to achieve your lock free stack. Since you intend to busy loop anyway to deal with compare and swap collisions, you can use the equivalent of a spin lock:

void lock_get () {
    while (!_sync_bool_compare_and_swap(&gGetLock, 0, 1)) {}
}

void unlock_get () {
    unlock_get_success = _sync_bool_compare_and_swap(&gGetLock, 1, 0);
    assert(unlock_get_success);
}

Now, the loop in test_get() can be surrounded by lock_get() and unlock_get(). The CAS loop of test_get() is just one thread contending with test_put(). Jens' implementation of the CAS loop seems cleaner though.

lock_get();
result = __sync_val_compare_and_swap(&gHead, 0, 0);
while ((oldval = result)) {
   result = __sync_val_compare_and_swap(&gHead, result, result->next);
   if (oldval == result) break;
}
unlock_get();

This implements the intention, which is that only one thread should be popping off the head.

Never access an atomic variable through a simple evaluation. Also, for a compare and swap loop like yours, __sync_val_compare_and_swap is more convenient, I think.

/* read the head atomically */
result = __sync_val_compare_and_swap(&gHead, 0, 0);
/* compare and swap until we succeed placing the next field */
while ((oldval = result)) {
   result = __sync_val_compare_and_swap(&gHead, result, result->next);
   if (oldval == result) break;
}

If you have a CAS variable (in your case gHead). You have to always use CAS to access it. Or protect it with a lock. For reading and writing. Stuff like "result = gHead;" is a big no-no.

Re-reading your question, a LIFO is a stack. Implementing any CAS based data structure is based on having only ONE thing to change. In a stack that is top-of-stack. You seem to be doing a linked list. I am sure there are cool ways to do an atomic linked list.

But for a stack, do one stack pointer, like everybody else :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!