如何在不同的调度队列中同步任务?

时间:2022-06-08 07:37:32

I'm new to queues and I'm having some trouble setting up the following scheme.

我是排队的新手,我在设置以下方案时遇到了一些麻烦。

I have three tasks that need doing.

我有三个需要做的任务。

Task A: Can only run on the main queue, can run asynchronously with task B, cannot run asynchronously with task C. Runs a lot but runs fairly quickly.

任务A:只能在主队列上运行,可以与任务B异步运行,不能与任务C异步运行。运行很多但运行速度相当快。

Task B: Can run on any queue, can run asynchronously with task A, cannot run asynchronously with task C. Runs rarely, but takes a long time to run. Needs Task C to run afterwards, but once again task C cannot run asynchronously with task A.

任务B:可以在任何队列上运行,可以与任务A异步运行,不能与任务C异步运行。运行很少,但需要很长时间才能运行。需要任务C以后运行,但任务C再次无法与任务A异步运行。

Task C: Can run on any queue. Cannot run asynchronously with either task A or task B. Runs rarely and runs quickly.

任务C:可以在任何队列上运行。无法与任务A或任务B异步运行。很少运行并快速运行。

Right now I have it like this:

现在我有这样的:

Task A is submitted to the main queue by a Serial Queue X (a task is submitted to Serial Queue X to submit task A to the main queue).

任务A由串行队列X提交到主队列(任务被提交到串行队列X以将任务A提交到主队列)。

Task B is submitted to Serial Queue X.

任务B提交给Serial Queue X.

Task C is submitted to the main queue by Serial Queue X, just like task A.

任务C由Serial Queue X提交到主队列,就像任务A一样。

The problem here is that task C sometimes runs at the same time as task B. The main queue sometimes runs task C at the same time that the serial queue runs task B.

这里的问题是任务C有时与任务B同时运行。主队列有时在串行队列运行任务B的同时运行任务C.

So, how can I ensure that task B and task C never run at the same time while still allowing A and B to run at the same time and preventing A and C from running at the same time? Further, is there any easy way to make sure they run the same number of times? (alternating back and forth)

那么,如何确保任务B和任务C不会同时运行,同时仍然允许A和B同时运行并防止A和C同时运行?此外,有没有简单的方法来确保它们运行相同的次数? (来回交替)

3 个解决方案

#1


2  

You know, I think I had this problem on my GRE, only A, B, and C were Bob, Larry, and Sue and they all worked at the same office.

你知道,我认为我的GRE有这个问题,只有A,B和C是Bob,Larry和Sue,他们都在同一个办公室工作。

I believe that this can be solved with a combination of a serial queue and a dispatch semaphore. If you set up a single-wide serial dispatch queue and submit tasks B and C to that, you'll guarantee that they won't run at the same time. You can then use a dispatch semaphore with a count set to 1 that is shared between tasks A and C to guarantee that only one of them will run at a time. I describe how such a semaphore works in my answer here. You might need to alter that code to use DISPATCH_TIME_FOREVER so that task A is held up before submission rather than just tossed aside if C is running (likewise for submission of C).

我相信这可以通过串行队列和调度信号量的组合来解决。如果设置单宽串行调度队列并将任务B和C提交给该队列,则可以保证它们不会同时运行。然后,您可以使用在任务A和C之间共享的计数设置为1的调度信号量,以保证一次只运行其中一个。我在这里描述了这样一个信号量是如何工作的。您可能需要更改该代码以使用DISPATCH_TIME_FOREVER,以便在提交之前保留任务A,而不是仅在C运行时抛弃(同样用于提交C)。

This way, A and B will be running on different queues (the main queue and your serial queue) so they can execute in parallel, but B and C cannot run at the same time due to their shared queue, nor can A and C because of the semaphore.

这样,A和B将在不同的队列(主队列和你的串行队列)上运行,因此它们可以并行执行,但由于它们的共享队列,B和C不能同时运行,A和C也不能信号量。

As far as load balancing on A and C goes (what I assume you want to balance), that's probably going to be fairly application-specific, and might require some experimentation on your part to see how to interleave actions properly without wasting cycles. I'd also make sure that you really need them to alternate evenly, or if you can get by with one running slightly more than another.

对于A和C上的负载平衡(我假设你想要平衡),这可能是相当特定于应用程序的,并且可能需要一些实验来查看如何正确地交错操作而不浪费周期。我还要确保你真的需要它们以均匀的方式交替,或者你可以通过一个比另一个更多的运行。

#2


0  

Did you check out NSOperation to synchronize your operations? You can handle dependencies there.

您是否检查过NSOperation以同步您的操作?你可以在那里处理依赖。

#3


0  

There's a much simpler way, of course, assuming that C must always follow A and B, which is to have A and B schedule C as completion callbacks for their own operations (and have C check to make sure it's not already running, in case A and B both ask for it to happen simultaneously). The completion callback pattern (described in dispatch_async man page) is very powerful and a great way of serializing async operations that need to be nonetheless coupled.

当然,有一种更简单的方法,假设C必须始终遵循A和B,即A和B将C作为自己操作的完成回调(并检查C以确保它尚未运行,以防万一) A和B都要求它同时发生)。完成回调模式(在dispatch_async手册页中描述)非常强大,是序列化异步操作的一种很好的方法,需要进行耦合。

Where the problem is A, B, C, D and E where A-D can run async and E must always run at the end, dispatch groups are a better solution since you can set E to run as the completion callback for the entire group and then simply put A-E in that group.

问题是A,B,C,D和E,其中AD可以运行异步,E必须始终运行在末尾,调度组是更好的解决方案,因为您可以将E设置为整个组的完成回调运行,然后简单地将AE放在该组中。

#1


2  

You know, I think I had this problem on my GRE, only A, B, and C were Bob, Larry, and Sue and they all worked at the same office.

你知道,我认为我的GRE有这个问题,只有A,B和C是Bob,Larry和Sue,他们都在同一个办公室工作。

I believe that this can be solved with a combination of a serial queue and a dispatch semaphore. If you set up a single-wide serial dispatch queue and submit tasks B and C to that, you'll guarantee that they won't run at the same time. You can then use a dispatch semaphore with a count set to 1 that is shared between tasks A and C to guarantee that only one of them will run at a time. I describe how such a semaphore works in my answer here. You might need to alter that code to use DISPATCH_TIME_FOREVER so that task A is held up before submission rather than just tossed aside if C is running (likewise for submission of C).

我相信这可以通过串行队列和调度信号量的组合来解决。如果设置单宽串行调度队列并将任务B和C提交给该队列,则可以保证它们不会同时运行。然后,您可以使用在任务A和C之间共享的计数设置为1的调度信号量,以保证一次只运行其中一个。我在这里描述了这样一个信号量是如何工作的。您可能需要更改该代码以使用DISPATCH_TIME_FOREVER,以便在提交之前保留任务A,而不是仅在C运行时抛弃(同样用于提交C)。

This way, A and B will be running on different queues (the main queue and your serial queue) so they can execute in parallel, but B and C cannot run at the same time due to their shared queue, nor can A and C because of the semaphore.

这样,A和B将在不同的队列(主队列和你的串行队列)上运行,因此它们可以并行执行,但由于它们的共享队列,B和C不能同时运行,A和C也不能信号量。

As far as load balancing on A and C goes (what I assume you want to balance), that's probably going to be fairly application-specific, and might require some experimentation on your part to see how to interleave actions properly without wasting cycles. I'd also make sure that you really need them to alternate evenly, or if you can get by with one running slightly more than another.

对于A和C上的负载平衡(我假设你想要平衡),这可能是相当特定于应用程序的,并且可能需要一些实验来查看如何正确地交错操作而不浪费周期。我还要确保你真的需要它们以均匀的方式交替,或者你可以通过一个比另一个更多的运行。

#2


0  

Did you check out NSOperation to synchronize your operations? You can handle dependencies there.

您是否检查过NSOperation以同步您的操作?你可以在那里处理依赖。

#3


0  

There's a much simpler way, of course, assuming that C must always follow A and B, which is to have A and B schedule C as completion callbacks for their own operations (and have C check to make sure it's not already running, in case A and B both ask for it to happen simultaneously). The completion callback pattern (described in dispatch_async man page) is very powerful and a great way of serializing async operations that need to be nonetheless coupled.

当然,有一种更简单的方法,假设C必须始终遵循A和B,即A和B将C作为自己操作的完成回调(并检查C以确保它尚未运行,以防万一) A和B都要求它同时发生)。完成回调模式(在dispatch_async手册页中描述)非常强大,是序列化异步操作的一种很好的方法,需要进行耦合。

Where the problem is A, B, C, D and E where A-D can run async and E must always run at the end, dispatch groups are a better solution since you can set E to run as the completion callback for the entire group and then simply put A-E in that group.

问题是A,B,C,D和E,其中AD可以运行异步,E必须始终运行在末尾,调度组是更好的解决方案,因为您可以将E设置为整个组的完成回调运行,然后简单地将AE放在该组中。