The original address: ali-akhtar.medium.com/concurrency…
This is the second part of the Swift concurrent programming series. This section describes the Dispatch Group.
The Dispatch Group has the following characteristics:
-
The Dispatch Group can block threads until one or more tasks complete and continue down. You can use this feature to complete tasks that need to wait for other tasks to complete.
-
After dispatching multiple tasks to calculate some data, you can use the Dispatch Group to wait for those tasks and then complete the post-processing results, although they may also run on different queues.
-
The Dispatch Group can perform task aggregation synchronization
usewait
As shown above, we did the following:
- Created a custom concurrent queue labeled “com.any.app. queue”
- A scheduling group is created
- use
group.enter()
Enter groups manually Note: the call to this function must be made withgroup.leave()
Balance, or the application will crash - through
queue.async
Perform task 1, which will return immediately and GCD will start running the task concurrently - Again using
group.enter()
Manually added to the group - through
queue.async
Perform task 2, again, it will return immediately and GCD will start running the task concurrently group.wait()
Will block any thread here until all of the above tasks are complete (so don’t use this function on the main thread), since we called this method on the main thread, it will block the main thread.
To avoid blocking the main thread, we can wait on background threads like this:
usenotify
In the previous section, we used queue asynchronous dispatch to avoid blocking the main thread, but that didn’t seem optimal. Because it always blocks a thread. Fortunately, the COMMUNIST Party of China offers a better solution to usenotify
You can be notified when all tasks are complete:
In the example below, #3 FINISHED is printed after tasks 1 and 3 are complete, but it does not wait for task 2 to complete. Because task 2 is not executed in the group.
After our transformation,#3 finished
Will be printed after all tasks are completed:
DispatchGroup.notify(qos:flags:queue:execute:)
Receiving a parameterqueue
To determine on which queue the completed task will be executed. If we specify the main queue, it will execute on the main thread:
barrier
Dispatch barriers
Is a set of andConcurrent queue
Functions that work together and provide similarserial
The ability to perform tasks.- When you submit a DispatchWorkItem (task) to a dispatch queue, you can set flags to indicate that it should be the only task to execute on a given queue at a particular time. This means that in
Dispatch barrier
All tasks submitted to the queue before a task must be completed before it begins execution.
For the above example:
- Create a concurrent queue
- Task 1 and task 2 are dispatched asynchronously
- At this point, the above two tasks are executed concurrently. In this case we use
barrier
Add task 3 as a sign that it will start executing after all previous tasks have completed, and no other tasks will be executed during task 3. - Continue adding task 4, which will be in
barrier
Task after execution
The results are as follows:
We use thebarrier
The assigned tasks are independent in the concurrent queueserial
The method is executed. Like this:
Read and write questions
If you read and write on multiple threads, you are bound to run into read and write problems. The Dispatch barrier can be used to implement the multi-read single-write model:
class ReadWriteSolution {
/// Dependent concurrent queue
let queue = DispatchQueue(label: "com.queue.rw", attributes: .concurrent)
private var _file = 0
var file: Int {
get {
// Read operations need to be returned synchronously
queue.sync {
return _file
}
}
set {
// Write operations need to be separated from other writes or reads
queue.async(flags: .barrier) { [self] in
self._file = newValue
}
}
}
}
Copy the code