There are several ways to implement thread synchronization under GCD Multithreading:
1. Serial Queue 2. Parallel Queue 3. Grouping 4. Semaphore
Example: Go online to get a picture and show it on the view. To achieve this requirement, you can split into two tasks, one to get pictures on the web, and one to display them on the view. The two tasks are related, so they need to be processed synchronously.
Here are some ways to do this.
One
1. Serial Queue
1.1[GCD Related:]
(1) The Dispatch_queue queues under GCD are FIFO queues and are executed in the order in which they are submitted to the queue.
Just according to the nature of the queue, divided into <1> serial queue: User queue, main thread queue <2> parallel queue.
(2) synchronous (Dispatch_sync), asynchronous (Dispatch_async) mode. Used with serial queues and parallel queues.
1.2 The synchronization queue is ready to submit two tasks directly.
String-shaped queue dispatch_queue_t Serilqueue = dispatch_queue_create ("Com.quains.myQueue", 0); Start time NSDate *starttime = [NSDate Date]; __block UIImage *image = nil; 1. First go to the online download image Dispatch_async (serilqueue, ^{nsstring *urlasstring = @ "HTTP://AVATAR.CSDN.NET/B/2/2/1_U010013695.J PG "; Nsurl *url = [Nsurl urlwithstring:urlasstring]; Nserror *downloaderror = nil; NSData *imagedata = [nsurlconnection sendsynchronousrequest:[nsurlrequest Requestwithurl:url] ReturningResponse:nil error:&downloaderror]; if (Downloaderror = = Nil && imageData! = nil) {image = [[UIImage imagewithdata:imagedata] retain]; } else if (downloaderror! = nil) {NSLog (@ "Error happened =%@", downloaderror); } else{NSLog (@ "No data download"); } }); 2. In the main thread display to the interface Dispatch_async (Serilqueue, ^{NSLog (@ "%@", [Nsthread CurrentThread]); The main thread shows Dispatch_async (Dispatch_get_main_queue (), ^{if (image! = nil) {Uiimagevie W *imageview = [[Uiimageview alloc] initWithFrame:self.view.bounds]; [ImageView Setimage:image]; [ImageView Setcontentmode:uiviewcontentmodescaleaspectfit]; [Self.view Addsubview:imageview]; [ImageView release]; NSDate *endtime = [NSDate Date]; NSLog (@ "serial async completed in%f time", [EndTime timeintervalsincedate:starttime]); } else{NSLog (@ "image isn ' t downloaded, nothing to display"); } }); }); 3. Cleaning up Dispatch_release (serilqueue); [Image release];
Attention:
(1) __block variable is allocated in the stack, retain, to prevent being recycled.
(2) Dispatch to manually create and release.
(3) When submitting to the main thread queue, it is prudent to use the synchronous Dispatch_sync method, which may cause deadlock. Because the main thread queue is a serial queue, it is necessary to wait for the tasks in the queue to be executed one at a time. So submit a task to the queue, if the synchronization method will block the main thread, and the main thread also waiting for the main thread queue to execute the task to execute that just submitted, so the main thread queue there are other tasks, But he has been blocked, unable to finish the other tasks in the queue first, that is, the last task did not have a chance to execute, resulting in a deadlock.
(4) Submission to serial queue can be synchronous or asynchronous.
2. Parallel queue
When using parallel queues, the task can be submitted to the queue in a synchronous way, that is, the synchronization can be achieved.
Create a new queue dispatch_queue_t Concurrentqueue = dispatch_get_global_queue (dispatch_queue_priority_default, 0); Memory NSDate *starttime = [NSDate Date]; Join Queue Dispatch_async (concurrentqueue, ^{__block UIImage *image = nil; 1. First go to the online download image Dispatch_sync (concurrentqueue, ^{nsstring *urlasstring = @ "http://avatar.csdn.net/B/2/2/1_ U010013695.jpg "; Nsurl *url = [Nsurl urlwithstring:urlasstring]; Nserror *downloaderror = nil; NSData *imagedata = [nsurlconnection sendsynchronousrequest:[nsurlrequest Requestwithurl:url] ReturningResponse:nil error:&downloaderror]; if (Downloaderror = = Nil && imageData! = nil) {image = [UIImage imagewithdata:imagedata]; } else if (downloaderror! = nil) {NSLog (@ "Error happened =%@", downloaderror); } else{NSLog (@ "No data downlOad "); } }); 2. In the main thread display to the interface Dispatch_sync (Dispatch_get_main_queue (), ^{if (image! = nil) {Uiimagevie W *imageview = [[Uiimageview alloc] initWithFrame:self.view.bounds]; [ImageView Setimage:image]; [ImageView Setcontentmode:uiviewcontentmodescaleaspectfit]; [Self.view Addsubview:imageview]; [ImageView release]; NSDate *endtime = [NSDate Date]; NSLog (@ "Parallel sync completed in%f time", [EndTime timeintervalsincedate:starttime]); } else{NSLog (@ "image isn ' t downloaded, nothing to display"); } }); });
Two synchronous tasks can be synchronized by using an asynchronous package and committing to a parallel queue.
3. How to use grouping
The 3.1 group itself combines several related tasks and provides the developer with a point that knows the end of the group.
Although there is only one task, it is possible to use the group's end point to block threads to achieve synchronization.
dispatch_group_t group = Dispatch_group_create (); dispatch_queue_t queue = dispatch_get_global_queue (0, 0); NSDate *starttime = [NSDate Date]; __block UIImage *image = nil; Dispatch_group_async (group, queue, ^{//1. First go to the online download image nsstring *urlasstring = @ "http://avatar.csdn. Net/b/2/2/1_u010013695.jpg "; Nsurl *url = [Nsurl urlwithstring:urlasstring]; Nserror *downloaderror = nil; NSData *imagedata = [nsurlconnection sendsynchronousrequest:[nsurlrequest Requestwithurl:url] ReturningResponse:nil error:&downloaderror]; if (Downloaderror = = Nil && imageData! = nil) {image = [[UIImage imagewithdata:imagedata] retain]; } else if (downloaderror! = nil) {NSLog (@ "Error happened =%@", downloaderror); } else{NSLog (@ "No data download"); } }); 2. Wait for the download and then refresh the main thread dispatch_group_notify (group, queue, ^{//In the main thread display to the interface Dispatch_async (dispatch _get_main_queue (), ^{if (image = nil) {Uiimageview *imageview = [[Uiimageview alloc] Initwith Frame:self.view.bounds]; [ImageView Setimage:image]; [Image release]; [ImageView Setcontentmode:uiviewcontentmodescaleaspectfit]; [Self.view Addsubview:imageview]; [ImageView release]; NSDate *endtime = [NSDate Date]; NSLog (@ "group sync completed in%f time", [EndTime timeintervalsincedate:starttime]); } else{NSLog (@ "image isn ' t downloaded, nothing to display"); } }); }); Release the Dispatch_release (group);
Dispatch_group are also created and released manually.
Dispatch_notify () provides a point to know when the group ends. Of course, you can also use Dispatch_wait () to block.
4. Signal Volume
The signal volume and the function of the locking is similar, can be used to realize the way of synchronization.
But semaphores are typically used to allow several threads to access a resource at the same time, and to control the number of threads accessed by the semaphore.
Signal volume is initialized to 1 dispatch_semaphore_t semaphore = dispatch_semaphore_create (1); dispatch_queue_t queue = dispatch_get_global_queue (0, 0); NSDate *starttime = [NSDate Date]; __block UIImage *image = nil; 1. First go to the online download picture Dispatch_async (queue, ^{//wait operation-1 dispatch_semaphore_wait (semaphore, Dispatch_tim E_forever); Start download NSString *urlasstring = @ "Http://avatar.csdn.net/B/2/2/1_u010013695.jpg"; Nsurl *url = [Nsurl urlwithstring:urlasstring]; Nserror *downloaderror = nil; NSData *imagedata = [nsurlconnection sendsynchronousrequest:[nsurlrequest Requestwithurl:url] ReturningResponse:nil error:&downloaderror]; if (Downloaderror = = Nil && imageData! = nil) {image = [[UIImage imagewithdata:imagedata] retain]; NSLog (@ "Heap%@", image); NSLog (@ "%d", [Image Retaincount]); } else if (downloaderror! = nil) { NSLog (@ "Error happened =%@", downloaderror); } else{NSLog (@ "No data download"); }//Signal Operation +1 dispatch_semaphore_signal (semaphore); }); 2. Wait until the download is ready and then in the Refresh main thread Dispatch_async (Dispatch_get_main_queue (), ^{/wait operation-1 Dispatch_semaphore_wai T (semaphore, Dispatch_time_forever); if (image = nil) {Uiimageview *imageview = [[Uiimageview alloc] initWithFrame:self.view.bounds]; [ImageView Setimage:image]; NSLog (@ "%d", [Image Retaincount]); [Image release]; [ImageView Setcontentmode:uiviewcontentmodescaleaspectfit]; [Self.view Addsubview:imageview]; [ImageView release]; NSDate *endtime = [NSDate Date]; NSLog (@ "Semaphore sync completed in%f time", [EndTime timeintervalsincedate:starttime]); } else{NSLog (@ "image isn ' t downloaded, noThing to display "); }//Signal Operation +1 dispatch_semaphore_signal (semaphore); });
The dispatch_wait blocks the thread and detects the value of the semaphore until the semaphore value is greater than 0 and starts down execution, while performing a 1 operation on the semaphore.
The dispatch_signal is a +1 operation.
Semaphore_create
Http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/semaphore_wait.html
Function -Create a new semaphore.
Synopsis
kern_return_tsemaphore_create (task_t task semaphore_t *semaphore int policy int value );
PARAMETERS
- task
-
[In Task port] The task receiving the send right of the newly created semaphore.
- semaphore
-
[out of Send right] The port naming the created semaphore.
- policy
-
[In scalar] The blocked thread wakeup policy for the newly created semaphore. Valid policies is:
-
Sync_policy_fifo
-
A first-in-first-out policy for scheduling thread wakeup.
-
Sync_policy_fixed_priority
-
A fixed priority policy for scheduling thread wakeup.
- value
-
[in scalar] The initial value of the semaphore count.
DESCRIPTION
The semaphore_create function creates a new semaphore, associates the created semaphore with the specified task, and returns a send right naming the new semaphore. In order to support a robust Producer/consumer communication service, Interrupt service Routines (ISR) must bes able to sig NAL semaphores. The Semaphore Synchronizer Service is designed to allow User-level device drivers to perform signal operations, Eliminatin G The need for event counters. Device drivers which utilize semaphores is responsible for creating (via semaphore_create) and exporting (via device_get_status) semaphores for user level access. Device driver semaphore creation is do at device initialization time. Device drivers may support multiple semaphores.
RETURN VALUES
-
Kern_invalid_argument
-
The task argument or the policy argument was invalid, or the initial value of the semaphore was invalid.
-
Kern_resource_shortage
-
The kernel could not allocate the semaphore.
-
Kern_success
The
-
semaphore was successfully created.
Related information
Functions: Semaphore_destroy, semaphore_signal, semaphore_signal_all, semaphore_ Wait, device_get_status.
Semaphore_wait
Function -Wait on the specified semaphore.
Synopsis
kern_return_t semaphore_wait (semaphore_t semaphore );
PARAMETERS
- semaphore
The
-
port naming the semaphore, the wait operation is being performed upon.
DESCRIPTION
The semaphore_wait function decrements the semaphore count. If The semaphore count is negative after decrementing, the calling thread blocks. Device Driver Interrupt Service routines (ISR) should never executesemaphore_wait, since waiting on a semaphore At the ISR level may, and often'll, leads to a deadlock.
RETURN VALUES
-
Kern_invalid_argument
-
The specified semaphore is invalid.
-
kern_terminated
-
The specified semaphore has been destroyed.
-
kern_aborted
-
The caller is blocked due to a negative count on the semaphore, and is awoken for a reason isn't related to the semaphore subsystem (e.g.
thread_terminate).
-
Kern_success
The
-
Semaphore wait operation was successful.
Related information
Functions: semaphore_create, Semaphore_destroy, semaphore_signal, semaphore_ Signal_all, device_get_status.
Use of iOS semaphores