Use of iOS semaphores

Source: Internet
Author: User
Tags gcd scalar semaphore

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.