一种简单无锁队列的实现

11 篇文章 0 订阅
9 篇文章 0 订阅

Disruptor是内存无锁并发框架,基于一个环数组作为缓冲,详见Disruptor-1.0

下面是自己设计的一个简易版,目前没有发现存在冲突或错误的测试用例。大家可以一起测试下。

package tianshui.lockfree.queue;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 并发生产者和消费者数不能多于queue的length,默认是2^16
 * @author 天水
 * @date 2013-4-9 上午11:42:10
 */
public class RingBuffer<T> implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6976960108708949038L;

	private volatile AtomicInteger head;
	
	private volatile AtomicInteger tail;
	
	private int length;
	
	final T EMPTY = null;
	
	private volatile T[] queue;
	
	public RingBuffer(Class<T> type, int length){
		this.head = new AtomicInteger(0);
		this.tail = new AtomicInteger(0);
		this.length = length == 0 ? 2 << 16 : length; // 默认2^16
		this.queue = (T[]) Array.newInstance(type, this.length);  
	}
	
	public void enQueue(T t){
		if(t == null) t= (T) new Object();
		// 阻塞 -- 避免多生成者循环生产同一个节点
		while(this.getTail() - this.getHead() >= this.length); 
		int ctail = this.tail.getAndIncrement();
		while(this.queue[this.getTail(ctail)] != EMPTY); // 自旋
		this.queue[this.getTail(ctail)] = t;
	}
	
	public T deQueue(){
		T t = null;
		// 阻塞 -- 避免多消费者循环消费同一个节点
		while(this.head.get() >= this.tail.get()); 
		int chead = this.head.getAndIncrement();
		while(this.queue[this.getHead(chead)] == EMPTY); // 自旋
		t = this.queue[this.getHead(chead)];
		this.queue[this.getHead(chead)] = EMPTY;
		return t;
	}
	
	public int getHead(int index){
		return index & (this.length - 1);
	}
	
	public int getTail(int index) {
		return index & (this.length - 1);
	}

	public int getHead() {
		return head.get() & (this.length - 1);
	}

	public int getTail() {
		return tail.get() & (this.length - 1);
	}

	public T[] getQueue() {
		return queue;
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

}

下面是测试代码:

package tianshui.lockfree.queue;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 天水
 * @date 2013-4-9 下午04:13:29
 */
public class TestBuffer {
	public static AtomicInteger index = new AtomicInteger(0);
	
	public static void main(String[] args){
		
		int tCount = 10; // thread count
		int length = 0;  // buffer length -> 2^16
		
		final RingBuffer<Integer> buffer = new RingBuffer<Integer>(Integer.class, length);
		// provider
		Runnable pr = new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					int tindex = index.getAndIncrement();
					buffer.enQueue(tindex);
					System.out.println("buffer enQueue: " + tindex);
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		// consumer
		Runnable cr = new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					Integer cindex = buffer.deQueue();
					System.out.println("buffer deQueue: " + cindex);
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		
		for(int i=0; i<tCount; i++){
			new Thread(cr).start();
		}
		
		for(int i=0; i<tCount; i++){
			new Thread(pr).start();
		}
	}
}


在C++中实现无锁队列通常需要使用原子操作来保证并发安全,一种常见的无锁数据结构是基于MPMC(Multiple Producer Multiple Consumer)的无锁队列,如`std::atomic<>`配合`std::queue`。这里提供一个简化版的无锁队列模板,基于`std::atomic_int`作为哨兵: ```cpp #include <atomic> #include <queue> template<typename T> class UnlockedQueue { private: std::queue<T> data_; std::atomic_int empty_{0}, full_{0}; public: void push(const T& value) { while (full_.load(std::memory_order_acquire) == 1) { // 超时处理或调度其他任务 // ... } data_.push(value); empty_.fetch_sub(1, std::memory_order_release); full_.fetch_add(1, std::memory_order_release); } bool try_pop(T& value) { if (empty_.load(std::memory_order_acquire) == 0) { value = data_.front(); data_.pop(); full_.fetch_sub(1, std::memory_order_release); empty_.fetch_add(1, std::memory_order_release); return true; } else { return false; } } }; ``` 这个实现中,`push()` 和 `try_pop()` 函数分别用于向队列添加元素和尝试从队列移除元素。通过原子操作,我们可以在多线程环境下安全地更新`empty_`和`full_`标志。 然而,需要注意的是这只是一个非常基础的示例,并不适合在实际生产环境中直接使用,因为性能可能会受到限制,比如在高并发场景下。对于更复杂的无锁队列实现,可能需要引入更复杂的数据结构,如FIFO双端队列(DRQS),或者使用锁-free算法,如CAS(Compare-and-Swap)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值