美文网首页Swift
Swift 线程安全加锁

Swift 线程安全加锁

作者: HCong | 来源:发表于2018-06-08 10:50 被阅读33次

在OC中有dispatch_once来实现,在Swift中我们需要自己来根据其原理来实现,类似于增加一个哨兵来标识是否执行过了

原子操作

对于一个资源,在写入或读取时,只允许在一个时刻一个角色进行操作,则为原子操作。Swift中 let 声明的资源,永远是原子性的。在我们购买火车票时需要保证票数不会在多个线程中同时进行修改,这时就可以使用这种方式来实现。

  • OC实现方式
// 加锁
@synchronized(<#token#>) {
    <#statements#>
}
  • Swift实现方式
objc_sync_enter(lock)
// TODO:
objc_sync_exit(lock)

购买火车票

// 在Playeground实现
import UIKit
var ticket = 10000

func buyTicket(userName: String) {
    DispatchQueue.global().async {
//        objc_sync_enter(ticket)
        let count = ticket - 1
        ticket = count
//        objc_sync_exit(ticket)
        print("\(userName)买了一张票,剩余票数\(ticket)")
    }
}

for i in 1 ... 200 {
    
    buyTicket(userName: "hc\(i)")
    
}

结果如下:

hc6买了一张票,剩余票数9999
hc3买了一张票,剩余票数9998
hc1买了一张票,剩余票数9999
hc4买了一张票,剩余票数9998
hc2买了一张票,剩余票数9999
hc7买了一张票,剩余票数9998
hc5买了一张票,剩余票数9998
hc8买了一张票,剩余票数9997
hc9买了一张票,剩余票数9997
hc10买了一张票,剩余票数9997
hc11买了一张票,剩余票数9996
hc12买了一张票,剩余票数9996
hc14买了一张票,剩余票数9995
hc13买了一张票,剩余票数9995
hc15买了一张票,剩余票数9994
hc16买了一张票,剩余票数9994
hc17买了一张票,剩余票数9994
hc19买了一张票,剩余票数9994
hc18买了一张票,剩余票数9994
hc20买了一张票,剩余票数9993
hc22买了一张票,剩余票数9993
hc21买了一张票,剩余票数9993
hc23买了一张票,剩余票数9993
hc24买了一张票,剩余票数9992
hc25买了一张票,剩余票数9992
hc26买了一张票,剩余票数9991
hc27买了一张票,剩余票数9991
hc28买了一张票,剩余票数9991
hc29买了一张票,剩余票数9991
···

将加锁部分objc_sync_enter(ticket),objc_sync_exit(ticket)打开后结果如下:

hc1买了一张票,剩余票数9999
hc9买了一张票,剩余票数9998
hc12买了一张票,剩余票数9997
hc17买了一张票,剩余票数9996
hc20买了一张票,剩余票数9995
hc21买了一张票,剩余票数9994
hc22买了一张票,剩余票数9993
hc23买了一张票,剩余票数9992
hc24买了一张票,剩余票数9991
hc25买了一张票,剩余票数9990
hc26买了一张票,剩余票数9989
hc27买了一张票,剩余票数9988
hc28买了一张票,剩余票数9987
hc33买了一张票,剩余票数9986
hc38买了一张票,剩余票数9985
hc42买了一张票,剩余票数9984
hc47买了一张票,剩余票数9983
hc51买了一张票,剩余票数9982
hc55买了一张票,剩余票数9981
···

dispatch_once在Swift中的实现

extension DispatchQueue {
    fileprivate static var _onceToken = [String]()
    
    static func once(token: String, block: () -> Void) {
        objc_sync_enter(self)
        
        defer {
            objc_sync_exit(self)
        }
        
        if _onceToken.contains(token) {
            return
        }
        _onceToken.append(token)
        block()
    }
}

相关文章

  • Swift 线程安全加锁

    在OC中有dispatch_once来实现,在Swift中我们需要自己来根据其原理来实现,类似于增加一个哨兵来标识...

  • 设计模式

    单例模式 非线程安全image.png 加锁: 函数结束自动释放锁线程安全有instance之后就没必要加锁了。但...

  • 环形队列RingBuffer--Java实现

    在多线程并发中,程序为了保证线程的安全,通常需要加锁。那有没有一种数据结构能够实现不加锁的线程安全呢?有,就是大名...

  • nonatomic和atomic的区别

    nonatomic:非线程安全 atomic:线程安全 atomic对属性的set 和get方法进行加锁,保证当前...

  • iOS 多线程:NSOperation、NSOperationQ

    线程安全解决方案:可以给线程加锁,在一个线程执行该操作的时候,不允许其他线程进行操作。iOS 实现线程加锁有很多种...

  • 线程安全(锁)

    示例1: 示例2: 未加锁 上锁后 基于上下文管理自动加锁 内置线程安全

  • 2019-03-07线程安全和非线程安全

    [JAVA中的线程安全与非线程安全] 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进...

  • 线程安全

    常见的线程安全操作 ①加锁同步synchronized Lock等 ②wait() notify()线程调度 已实...

  • Java核心(三)并发中的线程同步与锁(转)

    解决线程安全核心思想是:“要么只读,要么加锁”,解决线程安全的关键在于合理的使用Java提供的线程安全包java....

  • java多线程-线程安全

    什么是线程安全和线程不安全 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其...

网友评论

    本文标题:Swift 线程安全加锁

    本文链接:https://www.haomeiwen.com/subject/udvosftx.html