對于單生產(chǎn)者-單消費者的情況萝嘁,可以實現(xiàn)無鎖環(huán)形緩沖區(qū)财松,常見的實現(xiàn)如下:
public class RingBuffer {
private int mHead;
private int mTail;
private char[] mBuffer;
public RingBuffer(int size) {
if (size < 2) {
throw new Exception("size should be greater than 2");
}
mBuffer = new char[size];
mHead = 0;
mTail = 0;
}
public int length() {
return (mTail + mBuffer.length - mHead) % mBuffer.length;
}
public boolean isEmpty() {
return mHead == mTail;
}
public boolean isFull() {
return mHead == ((mTail + 1) % mBuffer.length);
}
public char read() {
if (isEmpty()) {
throw new Exception("buffer is already empty");
}
char ch = mBuffer[mHead];
mHead = (mHead + 1) % mBuffer.length;
return ch;
}
public void write(char ch) {
if (isFull()) {
throw new Exception("buffer is already full");
}
mBuffer[mTail] = ch;
mTail = (mTail + 1) % mBuffer.length;
}
}
mHead
表明下一個可讀取的位置瘪贱,mTail
表明下一個可寫入的位置,head和tail重合時辆毡,表明buffer是空的;為了區(qū)分empty和full,強制要求tail和head之間至少要空一個元素菜秦,也就是說對于size為N的數(shù)組實現(xiàn)的環(huán)形buffer,最多只能存放N - 1個元素胚迫。如果不做這樣的強制要求喷户,則無法區(qū)分empty和full唾那。因此访锻,數(shù)組的size要大于2才有效。read和write函數(shù)各自只修改了head和tail, 所以即使運行在不同的線程闹获,也能保證數(shù)據(jù)的一致性期犬。
對于size為N的數(shù)組實現(xiàn)的環(huán)形buffer,如果想實現(xiàn)最多可以存放N個元素避诽,則必須引入length變量龟虎,而且無法做到lock-free。也就是說沙庐,只借助head和tail, 無法區(qū)分empty和full, 所以要借助empty和full時head和tail的間隔不同來幫忙區(qū)分鲤妥。
public class RingBuffer {
private int mHead;
private int mTail;
private int mLength;
private char[] mBuffer;
public RingBuffer(int size) {
if (size < 1) {
throw new Exception("size should be greater than 0");
}
mBuffer = new char[size];
mHead = 0;
mTail = 0;
}
public int length() {
return mLength;
}
public boolean isEmpty() {
return length() == 0;
}
public boolean isFull() {
return length() == mBuffer.length;
}
public char read() {
if (isEmpty()) {
throw new Exception("buffer is already empty");
}
char ch = mBuffer[mHead];
mHead = (mHead + 1) % mBuffer.length;
mLength--;
return ch;
}
public void write(char ch) {
if (isFull()) {
throw new Exception("buffer is already full");
}
mBuffer[mTail] = ch;
mTail = (mTail + 1) % mBuffer.length;
mLength++;
}
}