我们如何在 Swift 中实现等待/通知

2024-04-11

在Java中,我们可以这样做:

synchronized(a) {
    while(condition == false) {
        a.wait(time);
    }
    //critical section ...
    //do something
}

上面是一个条件同步块,它等待条件成功才能执行临界区。

当执行 a.wait 时(例如 100 毫秒),线程在该持续时间内退出临界区,并且由对象 a 执行同步的其他一些临界区,这使得条件为真。

当条件成功时,当前线程下次进入临界区并评估条件时,循环退出并执行代码。

需要注意的要点: 1.同一个对象同步多个临界区。 2. 线程仅在等待期间不处于临界区。一旦wait出来,线程又回到临界区。

下面是在 Swift 4 中使用 DispatchSemaphore 执行相同操作的正确方法吗?

while condition == false {
    semaphore1.wait(duration)
}
semaphore1.wait()
//execute critical section
semaphore1.signal()

当我们进入临界区时,条件可能会被修改。

因此,我们可能必须执行如下操作才能实现 Java 行为。在 Swift 中是否有更简单的方法来做到这一点?

while true {
    //lock
    if condition == false {
        //unlock
        //sleep for sometime to prevent frequent polling
        continue
    } else {
        //execute critical section
        //...
        //unlock
        break
    }
}

信号量

你可以用以下方法解决这个问题DispatchSemaphore.

我们来看看这段代码。 在这里我们有一个semaphore, storage类型的属性String?和一个串行队列

let semaphore = DispatchSemaphore(value: 0)
var storage: String? = nil
let serialQueue = DispatchQueue(label: "Serial queue")

Producer

func producer() {
    DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
        storage = "Hello world!"
        semaphore.signal()
    }
}

这里我们有一个函数:

  1. 等待3秒
  2. 将“Hello world”写入存储
  3. 通过信号量发送信号

Consumer

func consumer() {
    serialQueue.async {
        semaphore.wait()
        print(storage)
    }
}

这里我们有一个函数

  1. 等待来自信号量的信号
  2. 打印存储内容

Test

现在我要运行consumer BEFORE the producer功能

consumer()
producer()

Result

Optional("Hello world!")

它是如何工作的?

func consumer() {
    serialQueue.async {
        semaphore.wait()
        print(storage)
    }
}

的身体consumer()函数异步执行到串行队列中。

serialQueue.async {
    ...
}

这相当于你的synchronized(a)。事实上,根据定义,串行队列将同时运行一个闭包。

闭包内的第一行是

semaphore.wait()

因此闭包的执行被停止,等待信号量发出绿灯。

这是在不同的队列(不是主队列)上发生的,因此我们不会阻塞主线程。

func producer() {
    DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
        storage = "Hello world!"
        semaphore.signal()
    }
}

现在 Producer() 被执行。它在与主队列不同的队列上等待 3 秒,然后填充storage并通过信号量发送信号。

Finally consumer()接收到信号并可以运行最后一行

print(storage)

操场

如果您想在 Playground 中运行此代码,请记住

import PlaygroundSupport

并运行这条线

PlaygroundPage.current.needsIndefiniteExecution = true
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我们如何在 Swift 中实现等待/通知 的相关文章

随机推荐