Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
来源:互联网 发布:java ssh2 linux交互 编辑:程序博客网 时间:2024/06/05 15:32
Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
Pseudocode from article of the above name in PODC96 (with two typos corrected), by Maged M. Michael and Michael L. Scott. Corrected version also appeared inJPDC, 1998.
The non-blocking concurrent queue algorithm performs well on dedicated as well as multiprogrammed multiprocessors with and without contention. The algorithm requires a universal atomic primitive,CAS orLL/SC.
The two-lock concurrent queue algorithm performs well on dedicated multiprocessors under high contention. Useful for multiprocessors without a universal atomic primitive.
Non-Blocking Concurrent Queue Algorithm
structure pointer_t {ptr: pointer to node_t, count: unsigned integer} structure node_t {value: data type, next: pointer_t} structure queue_t {Head: pointer_t, Tail: pointer_t} initialize(Q: pointer to queue_t) node = new_node()// Allocate a free node node->next.ptr = NULL// Make it the only node in the linked list Q->Head.ptr = Q->Tail.ptr = node// Both Head and Tail point to it enqueue(Q: pointer to queue_t, value: data type) E1: node = new_node()// Allocate a new node from the free list E2: node->value = value// Copy enqueued value into node E3: node->next.ptr = NULL// Set next pointer of node to NULL E4: loop// Keep trying until Enqueue is done E5: tail = Q->Tail// Read Tail.ptr and Tail.count together E6: next = tail.ptr->next// Read next ptr and count fields together E7: if tail == Q->Tail// Are tail and next consistent? // Was Tail pointing to the last node? E8: if next.ptr == NULL // Try to link node at the end of the linked list E9: if CAS(&tail.ptr->next, next, <node, next.count+1>) E10: break// Enqueue is done. Exit loop E11: endif E12: else// Tail was not pointing to the last node // Try to swing Tail to the next node E13: CAS(&Q->Tail, tail, <next.ptr, tail.count+1>) E14: endif E15: endif E16: endloop // Enqueue is done. Try to swing Tail to the inserted node E17: CAS(&Q->Tail, tail, <node, tail.count+1>) dequeue(Q: pointer to queue_t, pvalue: pointer to data type): boolean D1: loop // Keep trying until Dequeue is done D2: head = Q->Head // Read Head D3: tail = Q->Tail // Read Tail D4: next = head.ptr->next // Read Head.ptr->next D5: if head == Q->Head // Are head, tail, and next consistent? D6: if head.ptr == tail.ptr // Is queue empty or Tail falling behind? D7: if next.ptr == NULL // Is queue empty? D8: return FALSE // Queue is empty, couldn't dequeue D9: endif // Tail is falling behind. Try to advance it D10: CAS(&Q->Tail, tail, <next.ptr, tail.count+1>) D11: else // No need to deal with Tail // Read value before CAS // Otherwise, another dequeue might free the next node D12: *pvalue = next.ptr->value // Try to swing Head to the next node D13: if CAS(&Q->Head, head, <next.ptr, head.count+1>) D14: break // Dequeue is done. Exit loop D15: endif D16: endif D17: endif D18: endloop D19: free(head.ptr) // It is safe now to free the old node D20: return TRUE // Queue was not empty, dequeue succeeded
Two-Lock Concurrent Queue Algorithm
structure node_t {value: data type, next: pointer to node_t} structure queue_t {Head: pointer to node_t, Tail: pointer to node_t, H_lock: lock type, T_lock: lock type} initialize(Q: pointer to queue_t) node = new_node()// Allocate a free node node->next = NULL // Make it the only node in the linked list Q->Head = Q->Tail = node// Both Head and Tail point to it Q->H_lock = Q->T_lock = FREE// Locks are initially free enqueue(Q: pointer to queue_t, value: data type) node = new_node() // Allocate a new node from the free list node->value = value// Copy enqueued value into node node->next = NULL // Set next pointer of node to NULL lock(&Q->T_lock)// Acquire T_lock in order to access Tail Q->Tail->next = node// Link node at the end of the linked list Q->Tail = node// Swing Tail to node unlock(&Q->T_lock)// Release T_lock dequeue(Q: pointer to queue_t, pvalue: pointer to data type): boolean lock(&Q->H_lock) // Acquire H_lock in order to access Head node = Q->Head// Read Head new_head = node->next// Read next pointer if new_head == NULL// Is queue empty? unlock(&Q->H_lock)// Release H_lock before return return FALSE// Queue was empty endif *pvalue = new_head->value// Queue not empty. Read value before release Q->Head = new_head// Swing Head to next node unlock(&Q->H_lock)// Release H_lock free(node)// Free node return} TRUE// Queue was not empty, dequeue succeeded
- Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
- Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
- non-blocking and blocking mode
- Blocking/Non-Blocking IO and SYN/ASYN IO
- Verilog HDL 学习笔记2-blocking and non-blocking assignment
- 阻塞与非阻塞(blocking and non-blocking)
- Node(11) Event Driven and Non-blocking
- Non-blocking I/O and select()
- ISE错误:“Cannot mix blocking and non blocking assignments on signal ”
- ISE错误:“Cannot mix blocking and non blocking assignments on signal ”
- Mix of blocking and non-blocking assignments to variable <en> is not a recommended coding practice.
- Differences Between Windows and Unix Non-Blocking Sockets
- [LinkedIn面试]implement the take() and put() of blocking queue
- Blocking Queue
- Blocking vs. Non-Blocking Sockets
- Blocking vs. non-blocking sockets
- Callback,Non-Blocking,Blocking函数
- ISE verilog 综合错误提示:ERROR:Xst:880 - "Johnson_source.v" line 45: Cannot mix blocking and non blocking
- tomcat虚拟路径的几种配置方法
- uc脚本 4--常量等等
- hdu1237 简单计算器
- 字符串匹配KMP算法初探
- Sql Server中的日期与时间函数
- Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
- Tomcat 6.0 配置--虚拟目录的设置+多域名绑定
- 如果不是异地
- 在SharePoint 2010程序中使用Session
- 设计模式C++实现(6)——建造者模式
- Java写的小游戏贪吃蛇代码
- Zend Studio加载现有PHP项目
- Android ListView动画注意事项
- java反射