环形缓冲区(Circular Buffer)与环形队列类似,是一种数据结构,支持在固定容量下的高效读写操作。相比队列,环形缓冲区通常允许覆盖旧数据,这在某些场景(如实时数据流、日志处理)中非常有用。
实现步骤
核心变量:
- 缓冲区数组
buffer[]
:存储数据。 - 读指针
head
:指向下一个读取的位置。 - 写指针
tail
:指向下一个写入的位置。 - 容量
capacity
:缓冲区的总大小。 - 当前大小
size
:记录缓冲区中实际存储的数据个数(可选,用于非覆盖模式)。
操作方法:
- 写入数据(
write
):- 如果缓冲区未满,将数据写入
tail
。 - 更新
tail
为(tail + 1) % capacity
。 - 在覆盖模式下,若缓冲区已满,会覆盖最早的数据,并移动
head
。
- 如果缓冲区未满,将数据写入
- 读取数据(
read
):- 如果缓冲区为空,读取失败。
- 从
head
读取数据,更新head
为(head + 1) % capacity
。
- 检查状态:
- 缓冲区是否满:
size == capacity
。 - 缓冲区是否空:
size == 0
。
- 缓冲区是否满:
代码示例(c++)
template <typename T>
class ZDThreadSafeCircularBuffer {
private:
std::vector<T> buffer; // 环形缓冲区
int head; // 读指针
int tail; // 写指针
int capacity; // 缓冲区容量
int size; // 当前缓冲区中元素的数量
std::mutex mtx; // 互斥锁
std::condition_variable notEmpty; // 缓冲区非空条件变量
std::condition_variable notFull; // 缓冲区非满条件变量
public:
// 构造函数
explicit ZDThreadSafeCircularBuffer(int capacity)
: buffer(capacity), head(0), tail(0), capacity(capacity), size(0) {}
// 写入数据
void write(const T& value) {
std::unique_lock<std::mutex> lock(mtx);
notFull.wait(lock, [this]() { return size < capacity; }); // 等待缓冲区非满
buffer[tail] = value;
tail = (tail + 1) % capacity;
++size;
notEmpty.notify_one(); // 通知有新数据可读
}
// 读取数据
T read() {
std::unique_lock<std::mutex> lock(mtx);
notEmpty.wait(lock, [this]() { return size > 0; }); // 等待缓冲区非空
T value = buffer[head];
head = (head + 1) % capacity;
--size;
notFull.notify_one(); // 通知有新空间可写
return value;
}
// 非阻塞写入
bool tryWrite(const T& value) {
std::lock_guard<std::mutex> lock(mtx);
if (size >= capacity) {
return false; // 缓冲区已满,写入失败
}
buffer[tail] = value;
tail = (tail + 1) % capacity;
++size;
notEmpty.notify_one(); // 通知有新数据可读
return true;
}
// 非阻塞读取
std::optional<T> tryRead() {
std::lock_guard<std::mutex> lock(mtx);
if (size == 0) {
return std::nullopt; // 缓冲区为空,读取失败
}
T value = buffer[head];
head = (head + 1) % capacity;
--size;
notFull.notify_one(); // 通知有新空间可写
return value;
}
// 检查缓冲区是否为空
bool isEmpty() const {
std::lock_guard<std::mutex> lock(mtx);
return size == 0;
}
// 检查缓冲区是否已满
bool isFull() const {
std::lock_guard<std::mutex> lock(mtx);
return size == capacity;
}
// 获取缓冲区当前大小
int getSize() const {
std::lock_guard<std::mutex> lock(mtx);
return size;
}
// 获取缓冲区容量
int getCapacity() const {
return capacity;
}
};