
没有并发,没有编程. 对于多线程,很难绕过锁.
iOS开发中两种常见的锁类型:
1. 互斥锁: 一次只有一个线程可以获取一个互斥锁,其余线程被挂起.
2. 自旋锁: 一个线程获得自旋锁后,其他线程将继续循环并尝试添加锁. 当超出限制并且未成功获得锁定时,线程将被挂起.
自旋锁更适合保留时间较短的锁持有人,实际使用中更多的排他锁.
1. 互斥体,信号量
1. 符合NSLocking协议的四种类型的锁
四种类型的锁是:
NSLock,NSConditionLock,NSRecursiveLock,NSCondition
NSLocking协议
public protocol NSLocking {
public func lock()
public func unlock()
}
这里是从多个售票点同时售票的示例

var ticket = 20
var lock = NSLock()
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
let thread1 = Thread(target: self, selector: #selector(saleTickets), object: nil)
thread1.name = "售票点A"
thread1.start()
let thread2 = Thread(target: self, selector: #selector(saleTickets), object: nil)
thread2.name = "售票点B"
thread2.start()
}
@objc private func saleTickets() {
while true {
lock.lock()
Thread.sleep(forTimeInterval: 0.5) // 模拟延迟
if ticket > 0 {
ticket = ticket - 1
print("\(String(describing: Thread.current.name!)) 卖出了一张票,当前还剩\(ticket)张票")
lock.unlock()
}else {
print("oh 票已经卖完了")
lock.unlock()
break;
}
}
}
顾名思义,这两种方法是在遵守协议后实现的lock()和unlock()方法.
此外,NSLock,NSConditionLock,NSRecursiveLock和NSCondition具有自己的实现:
1. 除了NSCondition之外,所有三种类型的锁都有两种方法:
// 尝试去锁,如果成功,返回true,否则返回false open func `try`() -> Bool // 在limit时间之前获得锁,没有返回NO open func lock(before limit: Date) -> Bool
2. NSCondition条件锁:
// 当前线程挂起 open func wait() // 当前线程挂起,设置一个唤醒时间 open func wait(until limit: Date) -> Bool // 唤醒在等待的线程 open func signal() // 唤醒所有NSCondition挂起的线程 open func broadcast()
在调用wait()之后,NSCondition实例将使用现有的锁来解锁当前线程,然后使该线程进入睡眠状态,当信号()通知时,该线程被唤醒,然后当前线程被锁定,因此看起来似乎wait()一直持有该锁,但是根据Apple文档中的说明,直接将wait()视为线程锁不能保证线程安全.
3. NSConditionLock条件锁:
NSConditionLock是在NSCondition的帮助下实现的. 在NSCondition的基础上,添加了一个有限条件,并且定制程度可以高于NSCondition.
// 锁的时候还需要满足condition open func lock(whenCondition condition: Int) // 同try,同样需要满足condition open func tryLock(whenCondition condition: Int) -> Bool // 同unlock,需要满足condition open func unlock(withCondition condition: Int) // 同lock,需要满足condition和在limit时间之前 open func lock(whenCondition condition: Int, before limit: Date) -> Bool
4. NSRecurisiveLock递归锁:

定义一个锁,该锁可以多次锁定同一线程而不会导致死锁.
提供的几种方法类似于NSLock.
2. GCD DispatchSemaphore和围栏功能
1. DispatchSemaphore信号量:
DispatchSemaphore中的信号量可以解决资源抢占的问题,并支持信号通知和等待. 发送信号通知时,信号量为+1;每当发送等待信号时,信号量为-1,如果信号为0,则信号将处于等待状态. 它将一直执行到信号量大于0为止. 因此,我们通常将DispatchSemaphore的值设置为1.
下面给出了DispatchSemaphore封装类
class GCDSemaphore {
// MARK: 变量
fileprivate var dispatchSemaphore: DispatchSemaphore!
// MARK: 初始化
public init() {
dispatchSemaphore = DispatchSemaphore(value: 0)
}
public init(withValue: Int) {
dispatchSemaphore = DispatchSemaphore(value: withValue)
}
// 执行
public func signal() -> Bool {
return dispatchSemaphore.signal() != 0
}
public func wait() {
_ = dispatchSemaphore.wait(timeout: DispatchTime.distantFuture)
}
public func wait(timeoutNanoseconds: DispatchTimeInterval) -> Bool {
if dispatchSemaphore.wait(timeout: DispatchTime.now() + timeoutNanoseconds) == DispatchTimeoutResult.success {
return true
} else {
return false
}
}
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-200179-1.html
没用
包装好的话里面干燥不可能生虫
期待演员杨洋带来更好的作品