何时使用信号量代替调度组? [英] When to use Semaphore instead of Dispatch Group?

查看:95
本文介绍了何时使用信号量代替调度组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我知道如何使用 DispatchGroup ,以便进行理解问题,我已经尝试过:

I would assume that I am aware of how to work with DispatchGroup, for understanding the issue, I've tried:

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

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

For using the Semaphore, I implemented:

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方法中对其进行了调用.结果是:

and called it in the viewDidLoad method. The result is:

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都具有相同的目的(除非我误解了).

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

老实说,我不熟悉:何时使用信号量,尤其是在与DispachGroup一起工作时-可能-处理了该问题.

Honestly, I am unfamiliar with: when to use the Semaphore, especially when workin with DispachGroup -probably- handles the issue.

我想念的是什么?

推荐答案

从概念上讲,DispatchGroup和Semaphore都具有相同的目的(除非我误解了).

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

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

The above is not exactly true. You can use a semaphore to do the same thing as a dispatch group but it is much more general.

调度组用于您要处理的事情,这些事情可以一次完成,但是您需要等待它们全部完成后再执行其他操作.

Dispatch groups are used when you have a load of things you want to do that can all happen at once, but you need to wait for them all to finish before doing something else.

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

Semaphores can be used for the above but they are general purpose synchronisation objects and can be used for many other purposes too. The concept of a semaphore is not limited to Apple and can be found in many operating systems.

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

In general, a semaphore has a value which is a non negative integer and two operations:

  • 等待如果该值不为零,则将其递减,否则将阻塞,直到出现信号量信号为止.

  • wait If the value is not zero, decrement it, otherwise block until something signals the semaphore.

信号如果有线程在等待,请取消阻塞其中之一,否则增加该值.

signal If there are threads waiting, unblock one of them, otherwise increment the value.

不用说两个操作都必须是线程安全的.在过去,当您只有一个CPU时,您只需在处理值和等待线程的队列时禁用中断即可.如今,由于有多个CPU内核以及片上缓存等,因此变得更加复杂.

Needless to say both operations have to be thread safe. In olden days, when you only had one CPU, you'd simply disable interrupts whilst manipulating the value and the queue of waiting threads. Nowadays, it is more complicated because of multiple CPU cores and on chip caches etc.

在任何情况下,只要您拥有最多可以同时由N个线程访问的资源,就可以使用信号量.将信号量的初始值设置为N,然后等待它的前N个线程不会被阻塞,但是下一个线程必须等待,直到前N个线程之一发出信号量为止.最简单的情况是N =1.在这种情况下,信号量的行为就像互斥锁.

A semaphore can be used in any case where you have a resource that can be accessed by at most N threads at the same time. You set the semaphore's initial value to N and then the first N threads that wait on it are not blocked but the next thread has to wait until one of the first N threads has signaled the semaphore. The simplest case is N = 1. In that case, the semaphore behaves like a mutex lock.

信号量可用于模拟调度组.您从0开始启动sempahore,启动所有任务-跟踪已启动的任务数,然后等待该信号灯次数.每个任务在完成时都必须发出信号.

A semaphore can be used to emulate a dispatch group. You start the sempahore at 0, start all the tasks - tracking how many you have started and wait on the semaphore that number of times. Each task must signal the semaphore when it completes.

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

However, there are some gotchas. For example, you need a separate count to know how many times to wait. If you want to be able to add more tasks to the group after you have started waiting, the count can only be updated in a mutex protected block and that may lead to problems with deadlocking. Also, I think the Dispatch implementation of semaphores might be vulnerable to priority inversion. Priority inversion occurs when a high priority thread waits for a resource that a low priority has grabbed. The high priority thread is blocked until the low priority thread releases the resource. If there is a medium priority thread running, this may never happen.

您几乎可以使用其他更高级别的同步抽象可以做到的信号量来做任何事情,但是正确地做到这一点通常是一件棘手的事情. (希望)精心编写了更高级别的抽象,如果可能的话,您应该优先使用它们,而不是使用带有信号量的自己动手"实现.

You can pretty much do anything with a semaphore that other higher level synchronisation abstractions can do, but doing it right is often a tricky business to get right. The higher level abstractions are (hopefully) carefully written and you should use them in preference to a "roll your own" implementation with semaphores, if possible.

这篇关于何时使用信号量代替调度组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆