微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ios – 何时使用Semaphore而不是Dispatch Group?

我会假设我知道如何使用 DispatchGroup,为了解问题,我尝试过:
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        performUsingGroup()
    }

    func performUsingGroup() {
        let dq1 = dispatchQueue.global(qos: .userInitiated)
        let dq2 = dispatchQueue.global(qos: .userInitiated)

        let group = dispatchGroup()

        group.enter()
        dq1.async {
            for i in 1...3 {
                print("\(#function) dispatchQueue 1: \(i)")
            }
            group.leave()
        }

        group.wait()

        dq2.async {
            for i in 1...3 {
                print("\(#function) dispatchQueue 2: \(i)")
            }
        }

        group.notify(queue: dispatchQueue.main) {
            print("done by group")
        }
    }
}

结果 – 预期 – 是:

performUsingGroup() dispatchQueue 1: 1
performUsingGroup() dispatchQueue 1: 2
performUsingGroup() dispatchQueue 1: 3
performUsingGroup() dispatchQueue 2: 1
performUsingGroup() dispatchQueue 2: 2
performUsingGroup() dispatchQueue 2: 3
done by group

为了使用信号量,我实现了:

func performUsingSemaphore() {
    let dq1 = dispatchQueue.global(qos: .userInitiated)
    let dq2 = dispatchQueue.global(qos: .userInitiated)

    let semaphore = dispatchSemaphore(value: 1)

    dq1.async {
        semaphore.wait()
        for i in 1...3 {
            print("\(#function) dispatchQueue 1: \(i)")
        }
        semaphore.signal()
    }

    dq2.async {
        semaphore.wait()
        for i in 1...3 {
            print("\(#function) dispatchQueue 2: \(i)")
        }
        semaphore.signal()
    }
}

并在viewDidLoad方法调用它.结果是:

performUsingSemaphore() dispatchQueue 1: 1
performUsingSemaphore() dispatchQueue 1: 2
performUsingSemaphore() dispatchQueue 1: 3
performUsingSemaphore() dispatchQueue 2: 1
performUsingSemaphore() dispatchQueue 2: 2
performUsingSemaphore() dispatchQueue 2: 3

从概念上讲,dispachGroup和Semaphore都有同样的目的(除非我误解了一些东西).

老实说,我不熟悉:什么时候使用信号量,尤其是在与dispachGroup合作时 – 可能 – 处理问题.

我错过了什么部分?

解决方法

Conceptually,both of dispachGroup and Semaphore serve the same purpose (unless I misunderstand something).

以上并非完全正确.您可以使用信号量来执行与调度组相同的操作,但它更通用.

当您有大量想要做的事情可以一次性发生时使用调度组,但是您需要等待它们全部完成才能执行其他操作.

信号量可用于上述信号,但它们是通用同步对象,也可用于许多其他目的.信号量的概念不仅限于Apple,而且可以在许多操作系统中找到.

通常,信号量的值为非负整数和两个操作:

> wait如果该值不为零,则递减它,否则阻塞直到某些信号通知信号量.
> signal如果有线程在等待,则取消阻塞其中一个,否则递增该值.

不用说两个操作都必须是线程安全的.在过去,当你只有一个cpu时,你只需要在操作值和等待线程的队列时禁用中断.如今,由于多个cpu内核和片上缓存等,它更复杂.

在任何情况下,您都可以使用信号量,而且资源最多可以同时被N个线程访问.您将信号量的初始值设置为N,然后等待它的前N个线程不被阻止,但是下一个线程必须等到前N个线程中的一个已发信号通知信号量.最简单的情况是N = 1.在这种情况下,信号量的行为类似于互斥锁.

信号量可用于模拟调度组.你从0开始sempahore,开始所有的任务 – 跟踪你已经开始的数量,并等待信号量多次.每个任务必须在信号完成时发出信号.

但是,有一些陷阱.例如,您需要一个单独的计数才能知道要等待多少次.如果您希望在开始等待后能够向组中添加更多任务,则只能在互斥锁保护块中更新计数,这可能会导致死锁问题.此外,我认为信号量的dispatch实现可能容易受到优先级倒置的影响.当高优先级线程等待低优先级抓取的资源时,发生优先级倒置.高优先级线程被阻塞,直到低优先级线程释放资源.如果正在运行中优先级线程,则可能永远不会发生这种情况.

你可以用其他更高级别的同步抽象可以做的信号量做任何事情,但做正确的事情往往是一个棘手的事情来做对.更高级别的抽象是(希望)仔细编写的,如果可能的话,你应该优先使用它们而不是使用信号量“自己动手”实现.

原文地址:https://www.jb51.cc/iOS/331122.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐