IOS multi-thread lock Swift-demo Sample Summary

Source: Internet
Author: User
Tags gcd posix semaphore

What is a thread lock?

In the previous article summarizes too many threads, summed up the multi-threaded, thread lock is also must be a good summary of things, this article when the idea may write a lot of things, can only squeeze time a little slowly summed up, know the thread after the thread lock to understand what is "thread lock."

"Thread Lock" a piece of code can only be accessed by one thread at a time, in order to avoid having multiple threads accessing the same code at the same time, there is the concept of "lock", for example, when thread a accesses a section of code and enters this code, we add a "lock". At this time, thread B comes in again, because the lock thread B will wait for thread A to finish after the end of the "lock" thread B can then access the code, so that the same time to avoid multiple threads access to the same piece of code!

I believe the above explanation should understand the concept of "lock", but also know what it is for, let us give another example, a house after a person (thread) in the door locked, another person (thread) came after the person waiting for the front (thread) out, wait for the front of the people to open the door, It can only enter the room. This explanation believes that the concept of "lock" should be understood, but we have to emphasize that there is not too much "thing" (executing code, that is, task) to do between this "lock" and "unlock", otherwise it will cause too long wait! is to go to the multi-threaded real meaning and use!

Let's explain our usual thread lock.

Nslock

Nslock is the simplest mutex, and the following nscondition, Nsconditionlock, and Nsrecursivelock obey the Nslocking protocol, and we put it together, including the nslock we're talking about now, Let's take a look at what's in this nslock and see how it's in the code first:

Public protocol nslocking {public        func-lock () public    func unlock ()}open class Nslock:nsobject, nslocking {        Open func ' Try ' () bool    open func Lock (before limit:date), bool    @available (IOS 2.0, *)    open var nam E:string?}

Let's talk about this in one way:

1, lock and unlock are the most commonly used two methods of this class, "lock" and "unlock" method.

2, the Try () method is to try to lock, the failure will not block the thread, if the acquisition of a lock failure will not execute the lock code.

3, Lock (before Limit:date) This method is not acquired to the thread lock in the time after the parameter passed in, and if the expiration has not acquired to the thread lock to wake the threads, the return value is No.

Here is the example code that we use in our demo:

    var imagemutablearray:array<any> = Array.init () Let lock = Nslock.init () override Func Viewdidload () {        Super.viewdidload ()//Do any additional setup after loading the view. For I in 0...1000 {imagemutablearray.append ("imagearray===" +string (i))} print ( "The number of arrays you initialized is", imagemutablearray.count)}//MARK:-Starttestbtnaction override func Removefromdataimagea Rray (), Void {///We use multiple threads to delete something inside an array, so there is a problem of resource competition, let's see//You can first comment out the lock lock and unlock method here, the code Will crash in Imagemutablearray.removefirst ()//on thread-safe issues such as writing (no lock) http://www.jianshu.com/p/2fce6a0bb17b WH                                        Ile (True) {Lock.lock () if (Imagemutablearray.count > 0) { Imagemutablearray.removefirst ()}else{now = Cfabsolutetimegetcurrent () Let ResultSTring = "Operation start time:" + String (describing:then) + "\ n End time:" +string (describing:now) + "\ nthe entire operation:" +string (now! -then!)                        + "MS"/* Note: Modify UI to be in the main thread, not on child threads, just beginning to inadvertently report the following error */                        DispatchQueue.main.async {self.resulttextView.text = resultstring } return} lock.unlock ()}}

Nscondition

nscondition condition lock, first it also follows the Nslocking protocol, this and we said above Nslock is consistent, so its lock and unlock way and we said Nslock is the same, is the lock and unlock method, If you simply use it to solve the problem of thread synchronization, his simple usage is the same as the Nslock written earlier. But if we use nscondition as Nslock, it's really a waste! Nscondition also have their own wait and signal usage, this and the signal volume behind a bit similar, the signal volume below we say, look at the nscondition part of the code:

    MARK:-starttestbtnaction     override func Removefromdataimagearray (), Void {while                (true) {                                Lock.lock ()                if (Imagemutablearray.count > 0) {                                                imagemutablearray.removefirst ()                }else{now                                                = Cfabsolutetimegetcurrent ()                        Let resultstring = "Operation start time:" + String (describing:then) + "\ n End time:" +string (describing: Now) + "\ n the entire operation:" +string (now! -then!) + "MS"                        DispatchQueue.main.async {                                                                self.resulttextView.text = resultstring                        }                        return                }                Lock.unlock ()         }    }

Nsconditionlock

Nsconditionlock also implements the Nslocking protocol, but after testing you will find that the new can be relatively low. Nsconditionlock can also be a thread-safe waiting call between threads like Nscondition. Here is the code in our demo, written here is just the most basic locking unlocking code, first look at:

 var imagemutablearray:array<any> = Array.init () Let lock = Nsconditionlock.init () override Func Viewdidload ()        {super.viewdidload ()//Do any additional setup after loading the view. For I in 0...1000 {imagemutablearray.append ("imagearray===" +string (i))} PR Int ("nscondition Number of arrays initialized", Imagemutablearray.count)}//MARK:-Starttestbtnaction over Ride func Removefromdataimagearray (), Void {while (true) {loc K.lock () if (Imagemutablearray.count > 0) {Imagemutablea                        Rray.removefirst ()}else{now = Cfabsolutetimegetcurrent () Let resultstring = "Operation start time:" + String (describing:then) + "\ n End time:" +string (describing:now) + "\ nthe entire When acting: "+string (now! -then!)          + "MS"                                      DispatchQueue.main.async {                Self.resulttextView.text = resultstring} return} Lock.unlock ()}}

Nsrecursivelock

Sometimes there is a recursive call in the "lock Code", before the start of the recursive lock, recursive call will be repeated after the start of the method so that the repeated execution of the lock code eventually resulting in deadlock, this time can use a recursive lock to solve, that is, our nsrecursivelock, It is a recursive lock! The use of recursive locks can be repeated in a thread to acquire locks without causing deadlocks, in this process will also record the number of locks and release locks, only when the balance between the two are released, the following is the example of our demo:

 Recursive call to Func Removefromimagearray (), Void {Recursivelock.lock () if (Imagemutablearray.coun        t>0) {Imagemutablearray.removefirst () Self.removefromimagearray ()} Recursivelock.unlock ()}//MARK:-removefromdataimagearray//impersonation recursive call to override Func REMOVEFROMD Ataimagearray (), Void {Let dispatchgroup = Dispatchgroup.init () Let Dispatchqueue = Dispatch  Queue.init (Label:queuelabel, QoS:. Default, Attributes:. Concurrent) Dispatchqueue.async (Group:dispatchgroup, QoS:                . Default, Flags:DispatchWorkItemFlags.noQoS) {Self.removefromimagearray ()}            Dispatchgroup.notify (queue:DispatchQueue.main) {self.now = Cfabsolutetimegetcurrent () Let resultstring = "Operation start time:" + String (describing:self.then) + "\ n End time:" +string (describing:self.now) + "\ nthe entire function When: "+string (self.now! + 5elf.then!) + "MS" Self.resulttextView.text = resultstring}}

@synchronized

@synchronized you have to say it is simple, its usage is indeed relatively simple, to explore it deep, it is really a lot of things!  But we are in swift to discuss the thread lock, there is no longer use @synchronized, because in swift it is not used, the corresponding replacement of it is the following two sentences:Objc_sync_enter () in the middle is the code you need to lock Objc_sync_exit (), that same operation above we use this mutex to write the code as follows:

MARK:-Removefromdataimagearray    override func Removefromdataimagearray (), Void {while                (true) {                // Mutex                objc_sync_enter (self)                if (Imagemutablearray.count > 0) {                                                imagemutablearray.removefirst ()                } else{                                                now = cfabsolutetimegetcurrent ()                        Let resultstring = "Operation start time:" + String (describing:then) + "\ n End time:" + String (describing:now) + "\ n entire operation:" +string (now! -then!) + "MS"                        DispatchQueue.main.async {                                                                self.resulttextView.text = resultstring                        }                        return                }                Objc_sync_exit (self)        }    }

dispatch_semaphore_t Signal Volume

Dispatch_semaphore_t is belong to GCD inside of the thing, in front of the end of multi-threading when we say put it in our summary line lock, said, here we say some of this semaphore, dispatch_semaphore_t And the front @synchronized is the same as our OC, in our Swift is not written, all the content is in the Dispatchsemaphore, about the GCD aspect of the API comparison we made a table below, roughly speaking:

After you have read the comparison and summary of this picture, we say back to our topic: Dispatchsemaphore can see its main method:

Open Class Dispatchsemaphore:dispatchobject {}///dispatch_semaphoreextension dispatchsemaphore {//Send signal, let semaphore +1 method public func signal () Int//Wait, let the semaphore-1 method public func Wait ()///The following two methods can set the wait time, after this time if there is no signal volume greater than or equal to the initialization of the semaphore value The time//will go to execute code, equal to our lock is invalid public func wait (timeout:dispatchtime)-Dispatchtimeoutresult public func W     AIT (walltimeout:dispatchwalltime), dispatchtimeoutresult}extension dispatchsemaphore {/*!     * @function dispatch_semaphore_create * * @abstract * Creates new counting semaphore with an initial value. * * @discussion * Passing zero for the value are useful for when, threads need to reconcile * the Complet Ion of a particular event.     Passing a value greater than zero is * useful for managing a finite pool of resources, where the pool size is equal     * to the value. * * @param value * The starting value for the semaphore. Passing a value less than zero would * cause NULL to is returned.     * * @result * The newly created semaphore, or NULL on failure. */@available (IOS 4.0, *) public/*not inherited*/init (value:int)}

      &NBSP;OC and Swift are the same, but there are some differences in writing, and here we don't say OC anymore, so let's look directly at how Swift's code is written:

MARK:-Starttestbtnaction override Func Removefromdataimagearray (), Void {while (true                   {/* can also be directly written: semaphore.wait () A wait signal occurs here, the semaphore is 1, becomes 0, the subsequent task will be in the waiting state, Wait until the semaphore is greater than or equal to 1 at the time of execution, if the semaphore is not greater than or equal to the value of your initialization time, it is always in the waiting state of course, you can also be here this is the time to wait semaphore.wait (Timeou T:dispatchtime.init (Uptimenanoseconds:uint64 (10)) But after this time, the entry is the same as our lock failure.                                The problem is the corresponding crash, where to remove the method, you can try it yourself */_ = semaphore.wait (timeout:DispatchTime.distantFuture) if (Imagemutablearray.count > 0) {imagemut Ablearray.removefirst ()}else{now = Cfabsolutetimegetcurren T () Let resultstring = "Operation start time:" + String (describing:then) + "\ n End time:" +string (Describing:now) + " \ nthe entire operation: "+string (now! -then!)             + "MS"                                   DispatchQueue.main.async { Self.resulttextView.text = resultstring}//Don't forget                Add processing here, otherwise return is not executed below the semaphore.signal () code semaphore.signal () return }//Signal () method, which causes the semaphore to be +1 semaphore.signal ()}}

Posix

POSIX is quite similar to the dispatch_semaphore_t usage we wrote earlier, but to explore the essence of haul they are not a thing at all, POSIX is a set of conditional mutex APIs provided on the Unix/linux platform. If you only use the files in OC, you need to import the header file: pthread.h

In Swift it is not necessary, but in the use of either OC or Swift, the code is consistent, its main method is the following three, the rest of the specific code can see the demo or the following basic method:

1. Pthread_mutex_init Initialization method

2, Pthread_mutex_lock plus lock method

3, Pthread_mutex_unlock Unlock method

Class Posixcontroller:threadlockcontroller {var imagemutablearray:array<any> = Array.init () var Mutex:pthrea                d_mutex_t = pthread_mutex_t ()//Initialize pthread_mutex_t type variable override func Viewdidload () {super.viewdidload ()        Initialize Pthread_mutex_init (&mutex,nil)//Do any additional setup after loading the view.        For I in 0...1000 {imagemutablearray.append ("imagearray===" +string (i))} Print ("Nslock Number of arrays initialized", Imagemutablearray.count)}//MARK:-Starttestbtnaction override func Removefromdatai Magearray (), Void {while (true) {//Locking pthread_mutex_l Ock (&mutex) if (Imagemutablearray.count > 0) {imagem Utablearray.removefirst ()}else{now = Cfabsolutetimegetcurr                    ENT ()    Let resultstring = "Operation start time:" + String (describing:then) + "\ n End time:" +string (describing:now) + "\ nthe entire operation:" +string (now! -then!)                                                                + "MS" DispatchQueue.main.async { Self.resulttextView.text = resultstring} pthread_mutex_                        Unlock (&mutex); return}//Unlock Pthread_mutex_unlock (&mutex)}}/* S The actual function of the Deinit function of wift and the Dealloc function in OC is the same as the disposal of the object's release notification agent and so on is handled here */deinit {Pthread_mutex_destroy (&A  Mp;mutex); Release the data structure of the Lock}}

What else is left?

1,Osspinlock

The first thing to mention is that Osspinlock has been a bug, resulting in not fully guaranteed to be thread-safe, so this we know, probably understand, the specific problem can go here to take a closer look: no longer safe osspinlock

2,Dispatch_barrier_async/dispatch_barrier_sync

I said this "fence" function when I summed up gcd in the front, and I don't repeat it here.

3, the last is the address of the demo, this demo is intended to use Swift to try to imitate the UI, including the chat frame that part, previously written OC, this spring was used to write a swift, mainly to use the swift, And look at 4.0 of its new features, otherwise long not written, some things easier to forget!

Demogit Address

IOS multi-thread lock Swift-demo Sample Summary

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.