`

一种读写可并发进行的队列的实现方法

阅读更多
二.
int front()
{
return beg->data;
}
如果调用front()操作得时候,beg刚好被删除,就可能造成很严重得问题。如果front()和pop_front()都只在一个读线程中使用,问题不大。如果将这两个接口得功能合并,如下:
int pop_front()
{
int ret = beg->data
ListNode* oldBeg = beg;
beg = beg->next;
delete oldBeg;
return ret;
}
好像使用起来更方便。但考虑到我们最终实现得列表应该可以保存任何类型得数据,如果自定义得类型在函数退出时候执行拷贝构造函数时出现异常,那么列表状态无法恢复了。也就是说这个接口不是异常安全的接口。考虑这一点,还是分为两个独立的接口更好一些。
当然在使用pop_front和front之前必须确保列表不为空:
boolean empty()
{
return beg == end;
}
如果将非空判断放到front内,那么为空得时候应该返回什么值?不知道。最好是用户自己明白这种情况下的风险。
如果存在多个读线程,那么front()和pop_front(),empty()都需要利用同一个互斥量保证线程同步。Push_back不应该和上面上个接口在同一个线程中调用。如果只是这么一个书面规范,实际应用中也很容易因为疏忽没有遵守这个规则。因此我们可以考虑分别提供两个不同的界面给读线程和写线程,这就使用Adaptor模式了,如下:
class WriteList
{
private:
List& list;
public:
WriteList(list& list): this.list(list){}
void push_back(int data) { list.push_back(data); }
};
class ReadList
{
private:
List& list;
public:
ReadList(list& list): this.list(list){}
void pop_front() { list.pop_front(); }
int front() { return list.front(); }
boolean empty() { return list.empty(); }
}
这样读取数据的线程只看到ReadList, 写数据的线程只能看到WriteList,就可以防止使用人员误用这4个接口。
下面考虑查询列表大小的接口:
int size()
{
int size = 0;
ListNode* ptmp = beg;
for(ListNode* ptmp = beg; ptmp != end; ptmp = ptmp.next, size);
return size;
}
这个操作过程需要访问beg,end指向的内存空间中保存的数据,但是pop_front的实现可能导致被访问的beg已经执行无效区域,为了确保代码安全,所有线程调试信息中需要输出列表大小的地方都要和pop_front一样使用同一个互斥量,这既造成性能问题,又有使用上的不便。很多时候写线程是需要调用这个接口的,比如要限制线程的最大元素数量的时候或者调试信息需要。为了解决不用加锁,可以访问size接口,需要保证已经删除的节点的内存区域的next数据可用,也就是说,删除节点只清除节点保存的数据区域,其它数据都是可用的。如果不释放内存区域,必然导致内存泄漏,我们可以考虑将这些已经释放的节点用于保存push_back写入的数据。
一个环行的链表可以解决这个问题。
Struct ListNode
{
int data ;
ListNode* next;
ListNode(int v,ListNode* pnext = 0): data(v),next(pnext){}
}
struct List
{
ListNode* beg;
ListNode* end;
List():beg(new ListNode(0)),end(beg){end->next = end;}

}
首先构造一个环行链表,push_back的时候如果先前没有被释放的元素,则将新元素加到end后面,仍然维持环行链表的结构:
分享到:
评论

相关推荐

    一个c++11实现的无锁队列.zip

    无锁队列是一种高效、线程安全的数据结构,尤其在多线程环境下,它通过避免锁的使用来提高并发性能。C++11引入了原子操作(atomic operations)和线程支持库,使得无锁编程成为可能。在这个“一个c++11实现的无锁...

    cpp-一个快速多生产者多消费者的C11无锁并发队列

    无锁编程是一种编程范式,它避免了在共享数据上使用锁,而是通过原子操作(如CAS - Compare and Swap)来保证数据的一致性。C++11引入了对原子操作和线程支持的原生支持,使得实现这样的无锁数据结构成为可能。 在...

    行业分类-设备装置-一种对缓冲队列并发执行读、写访问的方法和设备.zip

    标题“行业分类-设备装置-一种对缓冲队列并发执行读、写访问的方法和设备”揭示了这个主题专注于在硬件或设备级别的缓冲队列上实现并发的读写操作。这种方法旨在提高系统的并行处理能力和吞吐量,特别是在多任务或多...

    自扩充的Lock-Free并发环形队列算法

    总结来说,自扩充的Lock-Free并发环形队列算法通过锁无关的机制实现了高效且动态扩展的并发队列,适用于高并发的场景。尽管实现复杂,但通过巧妙地利用原子操作和循环链表结构,可以在不牺牲性能的前提下,有效地...

    bank.rar_ATM模拟器_消息队列 _读写队列

    消息队列是一种异步通信机制,它允许应用程序将消息发送到队列,然后由接收端在适当的时间处理。在ATM模拟器中,消息队列可能被用来处理用户请求,如存款、取款、查询余额等。这样,当客户端发送请求时,服务器不必...

    网络游戏-基于并发无锁环形队列的网络速率实时统计方法.zip

    本文档“基于并发无锁环形队列的网络速率实时统计方法”探讨了一种高效、低延迟的技术手段,即使用并发无锁环形队列来实现这一目标。这种技术尤其适用于多线程环境,能够确保数据的安全性和一致性,同时减少锁的开销...

    行业分类-设备装置-一种基于旋转队列体制的多功能FIFO存储器及其读写方法.zip

    本话题着重讨论了一种创新的基于旋转队列体制的多功能FIFO存储器及其读写方法。这种设计旨在提高存储效率,降低延迟,并增强系统功能。 首先,我们来理解FIFO的基本原理。在FIFO存储器中,数据按照进入的顺序被存储...

    一个c++环形队列缓冲区

    环形缓冲区(Circular Buffer),又称循环队列,是一种高效的数据结构,在嵌入式系统、网络通信、多媒体处理等领域有着广泛的应用。它通过在固定大小的内存空间内循环利用来提高内存利用率和降低数据处理的延迟。 #...

    php实现的memcached队列类

    AB面轮值替换策略是一种常见的队列管理方式,通常通过两个或者多个“面”(即队列段)交替进行读写操作,以防止某个面被过度使用,保证了队列操作的均衡性。 在PHP实现的这个Memcached队列类中,有以下几个主要功能...

    C++ windows版 多生产者多消费者的队列实现

    在IT领域,多生产者多消费者(Multiple Producer-Multiple Consumer, MP-MC)模型是一种常见的并发编程模式,它主要用于处理数据共享的问题。在Windows环境下,使用C++来实现这一模型通常涉及到线程同步和互斥量等...

    c++11无锁队列的一种简单实现.pptx

    C++11无锁队列是一种在多线程环境中用于高效数据交换的技术,它避免了传统互斥锁带来的开销,从而提高了并发性能。在C++11中,无锁队列的实现主要依赖于新标准引入的多线程支持、原子操作和内存模型。 首先,我们来...

    redis的sorted set实现延时队列

    延时队列是一种特殊的队列,它的特性是元素不是立即被处理,而是要在设定的延迟时间后才被消费。Redis 的有序集合通过结合其成员的分数(score)功能,可以轻松实现这一功能。 **一、Redis 有序集合** 有序集合是 ...

    python-基于python实现的sqlite队列+方便处理sqlite并发.zip

    这样可以确保每个时刻只有一个线程在进行数据库操作,避免了并发冲突,同时也提供了一种线程安全的解决方案。 在实际应用中,队列的实现可能包括以下步骤: 1. 创建一个线程安全的队列实例。 2. 每个线程在需要进行...

    mysql 队列 实现并发读

    在IT领域,尤其是在数据库管理中,队列是一种关键的数据结构,尤其在处理并发读写场景时,其作用尤为重要。在MySQL环境下,队列通常通过表格的形式实现,每一行代表一个队列元素。队列的基本原则是先进先出(FIFO)...

    消息队列发送消息的C#代码实现

    在IT行业中,消息队列(Message Queue,MQ)是一种常用于进程间通信的技术,它可以有效地解耦系统组件,提高系统的可扩展性和容错性。在C#编程环境中,我们可以使用.NET框架提供的System.Messaging命名空间来操作...

    多线程与循环队列

    总结来说,多线程中的循环队列是一种强大的工具,它结合了多线程的并发优势和循环队列的高效特性,广泛应用于各种并发和多线程编程场景。在实际开发中,理解并熟练掌握这一技术,可以极大地提升程序的性能和可扩展性...

    完全公平队列的实现

    "完全公平队列"(Completely Fair Queueing,简称CFQ)是一种I/O调度算法,旨在为多个进程提供公平的磁盘访问时间。在Linux内核中,CFQ被广泛用于提升系统性能,特别是对于那些需要频繁读写硬盘的并发应用。 CFQ的...

    《java并发编程的核心方法和框架》

    《java并发编程的核心方法和框架》这本书旨在深入探讨这一主题,帮助开发者掌握Java环境下的并发处理技巧。 1. **线程基础** - **线程创建**:Java提供了两种主要的线程创建方式,一是通过实现`Runnable`接口,二...

    window消息队列(MSMQ)实现

    Windows消息队列(Message Queuing,简称MSMQ)是微软提供的一种可靠的消息传递技术,它允许应用程序在不同的时间、不同的网络连接状态以及不同的计算机之间交换信息。MSMQ通过存储和转发消息来确保即使在网络不稳定...

    线程安全型队列的实现

    队列是一种基本的数据结构,它遵循先进先出(FIFO)的原则。在单线程环境下,队列的插入(入队)和删除(出队)操作相对简单,但在多线程环境中,由于多个线程可能同时进行这些操作,如果不加以控制,就可能出现数据...

Global site tag (gtag.js) - Google Analytics