ios中常用的线程同步策略-synchronize …

来源:互联网 发布:小志网络赚钱博客 编辑:程序博客网 时间:2024/06/05 07:53

@synchronize 

   The @synchronized directiveis a convenient way to create mutex locks on the fly in Objective-Ccode.                             The @synchronized directivedoes what any other mutex lock would do—it prevents differentthreads from acquiring the same lock at the same time. In thiscase, however, you do not have to create the mutex or lock objectdirectly. Instead, you simply use any Objective-C object as a locktoken, as shown in the following example: 

- (void)myMethod:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}

    Theobject passed tothe @synchronized directiveis a unique identifier used to distinguish the protected block. Ifyou execute the preceding method in two different threads, passinga different object forthe anObj parameteron each thread, each would take its lock and continue processingwithout being blocked by the other. If you pass the same object inboth cases, however, one of the threads would acquire the lockfirst and the other would block until the first thread completedthe critical section.

    As aprecautionary measure,the @synchronized blockimplicitly adds an exception handler to the protected code. Thishandler automatically releases the mutex in the event that anexception is thrown. This means that in order to usethe @synchronized directive,you must also enable Objective-C exception handling in your code.If you do not want the additional overhead caused by the implicitexception handler, you should consider using the lockclasses. 

   Objective-C provides support for threadsynchronization and exception handling, which are explained in thischapter and in “ExceptionHandling.” To turn on support for thesefeatures, usethe -fobjc-exceptions switchof the GNU Compiler Collection (GCC) version 3.3 and later.

   Note: Using either ofthese features in a program renders the application runnable onlyin Mac OS X v10.3 and later because runtimesupport for exception handling and synchronization is not presentin earlier versions of the software. 

   Objective-C supports multithreading inapplications. Therefore, two threads can try to modify the sameobject at the same time, a situation that can cause seriousproblems in a program. To protect sections of code from beingexecuted by more than one thread at a time, Objective-C providesthe @synchronized() directive.

   The @synchronized()directivelocks a section of code for use by a single thread. Other threadsare blocked until the thread exits the protected code—that is, whenexecution continues past the last statement inthe @synchronized() block.

The @synchronized() directivetakes as its only argument any Objective-C object,including self. This object is knownas a mutual exclusionsemaphore or mutex. Itallows a thread to lock a section of code to prevent its use byother threads. You should use separate semaphores to protectdifferent critical sections of a program. It’s safest to create allthe mutual exclusion objects before the application becomesmultithreaded, to avoid race conditions.

   Listing 12-1 shows codethat uses self asthe mutex to synchronize access to the instance methods of thecurrent object. You can take a similar approach to synchronize theclass methods of the associated class, using the class objectinstead of self. In the latter case,of course, only one thread at a time is allowed to execute a classmethod because there is only one class object that is shared by allcallers.

Listing12-1  Locking a methodusing self

- (void)criticalMethod
{
@synchronized(self) {
// Critical code.
...
}
}

   Listing 12-2 shows ageneral approach. Before executing a critical process, the codeobtains a semaphore fromthe Account classand uses it to lock the critical section.The Account classcould create the semaphore inits initialize method.

Listing12-2  Locking a methodusing a custom semaphore

Account *account = [Account accountFromString:[accountField stringValue]];
// Get the semaphore.
id accountSemaphore = [Account semaphore];
@synchronized(accountSemaphore) {
// Critical code.
...
}

    TheObjective-C synchronization feature supports recursive andreentrant code. A thread can use a single semaphore several timesin a recursive manner; other threads are blocked from using ituntil the thread releases all the locks obtained with it; that is,every@synchronized() block is exitednormally or through an exception.

When code inan @synchronized() blockthrows an exception, the Objective-C runtime catches the exception,releases the semaphore (so that the protected code can be executedby other threads), and rethrows the exception to the next exceptionhandler.

 

NSLock

An NSLock objectimplements a basic mutex for Cocoa applications. The interface forall locks (including NSLock) isactually defined by theNSLocking protocol,which definesthe lock and unlock methods.You use these methods to acquire and release the lock just as youwould any mutex.

In addition to the standard locking behavior,the NSLock classadds the tryLock and lockBeforeDate: methods.The tryLock methodattempts to acquire the lock but does not block if the lock isunavailable; instead, the method simplyreturns NO.The lockBeforeDate:methodattempts to acquire the lock but unblocks the thread (andreturns NO) if the lock is notacquired within the specified time limit.

The following example shows how you could usean NSLock object tocoordinate the updating of a visual display, whose data is beingcalculated by several threads. If the thread cannot acquire thelock immediately, it simply continues its calculations until it canacquire the lock and update the display.

BOOL moreToDo = YES;
NSLock *theLock = [[NSLock alloc] init];
...
while (moreToDo) {
if ([theLock tryLock]) {
[theLock unlock];
}
}
0 0
原创粉丝点击