swift实现线程安全的栈和队列

实现一个线程安全的栈

这里使用数组来存储栈的数据。不足之处在于本例中的Stack可以无限扩容,更好的是初始化时候指定一个最大容量,防止不断扩容申请内存导致内存不够的问题。这里的线程安全使用一个串行队列来保证,实际上也可以通过加锁或者信号量甚至自旋锁来解决。

struct Stack<Element> {

    private var items: [Element]

    private var queue = DispatchQueue(label: "StackOperationQueue")

    public init(capacity: Int = 10) {
        items = [Element]()
        items.reserveCapacity(capacity)
    }

    mutating public func push(item: Element) {
        queue.sync {
            items.append(item)
        }
    }

    mutating public func pop() -> Element? {
        var item: Element?
        queue.sync {
            item = items.removeLast()
        }
        return item
    }
}

实现一个线程安全的队列

// 存储数据的双向链表节点
class DoubleLinkNode<Element> {
    var previous: DoubleLinkNode?
    var next: DoubleLinkNode?
    let val: Element?
    init(val: Element?) {
        self.val = val
    }
    //声明==运算符,便于判断两个节点是否相等
    static func ==(left: DoubleLinkNode<Element>, right: DoubleLinkNode<Element>) -> Bool {
        //最准确的做法是判断内存地址是否相同
        let leftPointValue = Unmanaged<AnyObject>.passUnretained(left).toOpaque()
        let rightPointValue = Unmanaged<AnyObject>.passUnretained(right).toOpaque()
        return leftPointValue == rightPointValue
    }
}

/*
 1.使用双向链表实现队列结构,声明空的head/last哨兵节点简化双向链表操作;
 2.使用串行队列保证线程安全,实际上也可以通过加锁的方式实现线程安全;
 3.对于生产者-消费者模型,这里可以使用semaphore来实现,当队列为空的时候,让线程休眠,当有元素入队的时候唤醒一个线程继续执行任务。
 */
struct Queue<Element> {
    //声明串行队列,将操作放在串行队列中,保证线程安全
    private var queue = DispatchQueue(label: "QueueOperationQueue")

    let firstNode: DoubleLinkNode<Element>
    let lastNode: DoubleLinkNode<Element>

    public init(capacity: Int = 20) {
        firstNode = DoubleLinkNode(val: nil)
        lastNode = DoubleLinkNode(val: nil)
        firstNode.next = lastNode
        lastNode.previous = firstNode
    }

    /// 入队操作
    mutating public func enqueue(item: Element) {
        queue.sync {
            let node = DoubleLinkNode<Element>(val: item)
            let tmp = firstNode.next
            firstNode.next = node
            node.previous = firstNode
            node.next = tmp
            tmp?.previous = node
        }
    }

    /// 出队操作
    mutating public func dequeue() -> Element? {
        guard let previous = lastNode.previous, !(firstNode == previous) else { return nil }
        var node: DoubleLinkNode<Element>? = nil
        queue.sync {
            node = lastNode.previous
            node?.next = nil
            node?.previous = nil
            let tmp = node?.previous
            lastNode.previous = tmp
            tmp?.next = lastNode
        }
        return node?.val
    }
}

原文地址:https://www.cnblogs.com/dev-walden/p/11396048.html

时间: 2024-08-05 09:00:45

swift实现线程安全的栈和队列的相关文章

浅谈算法和数据结构(1):栈和队列

浅谈算法和数据结构(1):栈和队列 2014/11/03 ·  IT技术                                         · 2 评论                                      ·  数据结构, 栈, 算法, 队列 分享到: 60 SegmentFault D-Day 2015 北京:iOS 站 JDBC之“对岸的女孩走过来” CSS深入理解之relative HTML5+CSS3实现春节贺卡 原文出处: 寒江独钓   欢迎分享原创

栈和队列数据结构

栈和队列都是常用的数据结构.栈的应用非常的广泛,其原理也是非常经典的. 一.栈 ①栈(stack)又名堆栈,他是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一段被称为栈顶,相对地,把另一端称为栈底. ②栈就是一个桶,后放进去的先拿出来,它下面本来有的东西要等它出来之后出来(先进后出→FILO----FirstIn/LastOut) ③栈是操作系统在建立某个进程时或者线程(在支持多线程的操作系统是线程)为这个线程建立的存储区域,该区域具有FIFO的特性,在编译的时候可以指定

java集合详解(附栈,队列)

1 集合 1.1 为什么会出现集合框架 [1] 之前的数组作为容器时,不能自动拓容 [2] 数值在进行添加和删除操作时,需要开发者自己实现添加和删除. 1.2 Collection接口 1.2.1 Collection基础API Java集合框架提供了一套性能优良.使用方便的接口和类,它们位于java.util包中. Collection表示集合的根接口,可以看成一个容器,存储了很多对象,这些对象称为Collection元素.Collection要求元素必须是引用数据类型. Collection

纯数据结构Java实现(2/11)(栈与队列)

栈和队列的应用非常多,但其起实现嘛,其实很少人关心. 虽然苹果一直宣传什么最小年龄的编程者,它试图把编程大众化,弱智化,但真正的复杂问题,需要抽丝剥茧的时候,还是要 PRO 人士出场,所以知根知底,实在是必要之举(而非无奈之举). 大门敞开,越往里走越窄,竞争会越激烈. 栈 基本特性 就一条,FILO.但是用在其他复杂数据结构,比如树,或者用在其他应用场景的时候,比如记录调用过程中的变量及其状态等,超有用. 应用举例 比如 撤销操作: 用户每次的录入都会入栈,被系统记录,然后写入文件:但是用户撤

快速记忆数组栈和队列函数push()和shift()

在js中,对数组的操作是比较常见的,有时候,我们需要模拟栈和队列的特性才能实现需求,今天来给大家用通俗易懂.简洁明了的几行文字,来告诉大家栈和队列的几个函数,如何快速记住. 首先,概念还是要知道的: 栈(stack)又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素:从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻

3-3-行编辑程序-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第3章  栈和队列 - 行编辑程序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceStack.c        相关测试数据下载  链接? 无数据

用栈实现队列的效果

用两个栈实现队列的效果,可以入栈,出栈,判空等... 实现的栈基本功能 lstack.h #ifndef _LSTACK_H #define _LSTACK_H #include <stdexcept> using namespace std; // 基于链式表的堆栈 class Stack { public: // 构造过程中初始化为空堆栈 Stack (void) : m_top (NULL) {} // 析构过程中销毁剩余的节点 ~Stack (void) { for (Node* ne

javascript中的栈、队列。

                       javascript中的栈.队列 栈方法     栈是一种LIFO(后进先出)的数据结构,在js中实现只需用到2个函数 push()  接受参数并将其放置数组尾,并返回修改后的数组长度. pop()  移除数组尾的最后一项,并返回移除项的值. 事例: var colors = new Array();var count = colors.push("red","green"); count = colors.push(&

数据结构之栈和队列

数据结构学习继续向前推进,之前对线性表进行了学习,现在我们进入栈和队列的学习.同样我们先学习一些基本概念以及堆栈的ADT. 栈和队列是两种中重要的线性结构.从数据结构角度看,栈和队列也是线性表,只不过是受限的线性表.因此可以称为限定性数据结构.但从数据类型来看,他们是和线性表大不相同的两类重要的抽象数据类型. 栈:(stack)是限定仅在表尾进行相应插入和删除操作的线性表.因此,对栈来说,表尾有其特殊含义,称为栈顶,表头称为栈底,不含元素的空表称为空栈.栈一个重要特性就是后进先出.OK,我们来看