Thread Safety Summary

原文网址:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html

Thread Safety Summary

This appendix describes the high-level thread safety of some key frameworks in OS X and iOS. The information in this appendix is subject to change.

附录描述了在osx和ios中一些关键的框架的高水平的一些线程安全,在附录里的这些信息有可能发生改变

Cocoa

Guidelines for using Cocoa from multiple threads include the following:

  • Immutable objects are generally thread-safe. Once you create them, you can safely pass these objects to and from threads. On the other hand, mutable objects are generally not thread-safe. To use mutable objects in a threaded application, the application must synchronize appropriately. For more information, see Mutable Versus Immutable.
  • 不可变对象一般是线程安全的,一旦你 创建他们,你就能安全的将这些对象传递给这些线程。另一方面, 可变对象通常是线程不安全的。为了在一个线程应用里面使用这些可变的对象,这个应用必须恰当的同步。
  • Many objects deemed “thread-unsafe” are only unsafe to use from multiple threads. Many of these objects can be used from any thread as long as it is only one thread at a time. Objects that are specifically restricted to the main thread of an application are called out as such.

  • 许多认为不安全的对象也只是在多线程中使用不安全,这些对象中的许多能在任何线程中使用,只要在一个时间里面它是一个单一线程。当然那些被限制在只能在一个应用的主线程使用的对象排除在外。
  • The main thread of the application is responsible for handling events. Although the Application Kit continues to work if other threads are involved in the event path, operations can occur out of sequence.
  • 应用的主线程负责处理事件,尽管当其他线程也参与到那个特定的事件路径时,应用的工具包还能继续工作,但是操作就可能失序了。
  • If you want to use a thread to draw to a view, bracket all drawing code between the lockFocusIfCanDraw andunlockFocus methods of NSView.
  • To use POSIX threads with Cocoa, you must first put Cocoa into multithreaded mode. For more information, seeUsing POSIX Threads in a Cocoa Application

Foundation Framework Thread Safety

There is a misconception that the Foundation framework is thread-safe and the Application Kit framework is not. Unfortunately, this is a gross generalization and somewhat misleading. Each framework has areas that are thread-safe and areas that are not thread-safe. The following sections describe the general thread safety of the Foundation framework

有一个误导的观念是基础框架是线程安全的而应用工具包框架不是安全的。不幸的是,这么总结的概括有些误导,每个框架都有一些事线程安全,一些事线程不安全的,下面的部分描述了基础框架的一些线程安全。

Thread-Safe Classes and Functions

The following classes and functions are generally considered to be thread-safe. You can use the same instance from multiple threads without first acquiring a lock.

  • NSArray

  • NSAssertionHandler

  • NSAttributedString

  • NSCalendarDate

  • NSCharacterSet

  • NSConditionLock

  • NSConnection

  • NSData

  • NSDate

  • NSDecimal functions

  • NSDecimalNumber

  • NSDecimalNumberHandler

  • NSDeserializer

  • NSDictionary

  • NSDistantObject

  • NSDistributedLock

  • NSDistributedNotificationCenter

  • NSException

  • NSFileManager (in OS X v10.5 and later)

  • NSHost

  • NSLock

  • NSLog/NSLogv

  • NSMethodSignature

  • NSNotification

  • NSNotificationCenter

  • NSNumber

  • NSObject

  • NSPortCoder

  • NSPortMessage

  • NSPortNameServer

  • NSProtocolChecker

  • NSProxy

  • NSRecursiveLock

  • NSSet

  • NSString

  • NSThread

  • NSTimer

  • NSTimeZone

  • NSUserDefaults

  • NSValue

  • NSXMLParser

  • Object allocation and retain count functions

  • Zone and memory functions

Thread-Unsafe Classes

The following classes and functions are generally not thread-safe. In most cases, you can use these classes from any thread as long as you use them from only one thread at a time. Check the class documentation for additional details.

  • NSArchiver

  • NSAutoreleasePool

  • NSBundle

  • NSCalendar

  • NSCoder

  • NSCountedSet

  • NSDateFormatter

  • NSEnumerator

  • NSFileHandle

  • NSFormatter

  • NSHashTable functions

  • NSInvocation

  • NSJavaSetup functions

  • NSMapTable functions

  • NSMutableArray

  • NSMutableAttributedString

  • NSMutableCharacterSet

  • NSMutableData

  • NSMutableDictionary

  • NSMutableSet

  • NSMutableString

  • NSNotificationQueue

  • NSNumberFormatter

  • NSPipe

  • NSPort

  • NSProcessInfo

  • NSRunLoop

  • NSScanner

  • NSSerializer

  • NSTask

  • NSUnarchiver

  • NSUndoManager

  • User name and home directory functions

Note that although NSSerializerNSArchiverNSCoder, and NSEnumerator objects are themselves thread-safe, they are listed here because it is not safe to change the data objects wrapped by them while they are in use. For example, in the case of an archiver, it is not safe to change the object graph being archived. For an enumerator, it is not safe for any thread to change the enumerated collection.

Main Thread Only Classes

The following class must be used only from the main thread of an application.

  • NSAppleScript

Mutable Versus Immutable

Immutable objects are generally thread-safe; once you create them, you can safely pass these objects to and from threads. Of course, when using immutable objects, you still need to remember to use reference counts correctly. If you inappropriately release an object you did not retain, you could cause an exception later.

不可变的对象通常是线程安全的,一旦你创建他们,你能安全的传递这些对象给线程,当然,在使用不可变对象时,你扔需要记住安全地使用引用计数,如果你不恰当的释放了一个你根本没有引用的对象,那么你可能在以后引起一个异常。

Mutable objects are generally not thread-safe. To use mutable objects in a threaded application, the application must synchronize access to them using locks. (For more information, see Atomic Operations). In general, the collection classes (for example, NSMutableArrayNSMutableDictionary) are not thread-safe when mutations are concerned. That is, if one or more threads are changing the same array, problems can occur. You must lock around spots where reads and writes occur to assure thread safety.

可变对象通常是线程不全的,在一个线程应用中使用可变对象时,应用必须使用锁接近他们,通常情况下,容器类,例如可变数组和可变字典 ,当突变发生时,线程是不安全的。换句话说,如果一个或者多个线程在改变相同的数组,问题可能就会出现,你必须锁住读和写发生的点以确保线程安全。

Even if a method claims to return an immutable object, you should never simply assume the returned object is immutable. Depending on the method implementation, the returned object might be mutable or immutable. For example, a method with the return type of NSString might actually return an NSMutableString due to its implementation. If you want to guarantee that the object you have is immutable, you should make an immutable copy.

如果一个方法申明返回一个不可变的对象,你决不应该简单的认为返回类型就是不可变的,依靠这方法的实现,这返回对象可能是可变的或者不可变的,例如,一个方法拥有一个不可变的字符串事实上因为实现方法返回一个可变的字符串,如果你想要确保这个对象是不可变的,你应该做一个不可变的的copy.


Reentrancy

Reentrancy is only possible where operations “call out” to other operations in the same object or on different objects. Retaining and releasing objects is one such “call out” that is sometimes overlooked.

The following table lists the portions of the Foundation framework that are explicitly reentrant. All other classes may or may not be reentrant, or they may be made reentrant in the future. A complete analysis for reentrancy has never been done and this list may not be exhaustive.

  • Distributed Objects

  • NSConditionLock

  • NSDistributedLock

  • NSLock

  • NSLog/NSLogv

  • NSNotificationCenter

  • NSRecursiveLock

  • NSRunLoop

  • NSUserDefaults

Class Initialization

The Objective-C runtime system sends an initialize message to every class object before the class receives any other messages. This gives the class a chance to set up its runtime environment before it’s used. In a multithreaded application, the runtime guarantees that only one thread—the thread that happens to send the first message to the class—executes the initialize method. If a second thread tries to send messages to the class while the first thread is still in the initialize method, the second thread blocks until the initialize method finishes executing. Meanwhile, the first thread can continue to call other methods on the class. The initialize method should not rely on a second thread calling methods of the class; if it does, the two threads become deadlocked.

Due to a bug in OS X version 10.1.x and earlier, a thread could send messages to a class before another thread finished executing that class’s initialize method. The thread could then access values that have not been fully initialized, perhaps crashing the application. If you encounter this problem, you need to either introduce locks to prevent access to the values until after they are initialized or force the class to initialize itself before becoming multithreaded.

Autorelease Pools

Each thread maintains its own stack of NSAutoreleasePool objects. Cocoa expects there to be an autorelease pool always available on the current thread’s stack. If a pool is not available, objects do not get released and you leak memory. An NSAutoreleasePool object is automatically created and destroyed in the main thread of applications based on the Application Kit, but secondary threads (and Foundation-only applications) must create their own before using Cocoa. If your thread is long-lived and potentially generates a lot of autoreleased objects, you should periodically destroy and create autorelease pools (like the Application Kit does on the main thread); otherwise, autoreleased objects accumulate and your memory footprint grows. If your detached thread does not use Cocoa, you do not need to create an autorelease pool.

Run Loops

Every thread has one and only one run loop. Each run loop, and hence each thread, however, has its own set of input modes that determine which input sources are listened to when the run loop is run. The input modes defined in one run loop do not affect the input modes defined in another run loop, even though they may have the same name.

The run loop for the main thread is automatically run if your application is based on the Application Kit, but secondary threads (and Foundation-only applications) must run the run loop themselves. If a detached thread does not enter the run loop, the thread exits as soon as the detached method finishes executing.

Despite some outward appearances, the NSRunLoop class is not thread safe. You should call the instance methods of this class only from the thread that owns it.

Application Kit Framework Thread Safety

The following sections describe the general thread safety of the Application Kit framework.

Thread-Unsafe Classes

The following classes and functions are generally not thread-safe. In most cases, you can use these classes from any thread as long as you use them from only one thread at a time. Check the class documentation for additional details.

  • NSGraphicsContext. For more information, see NSGraphicsContext Restrictions.

  • NSImage. For more information, see NSImage Restrictions.

  • NSResponder

  • NSWindow and all of its descendants. For more information, see Window Restrictions.

Main Thread Only Classes

The following classes must be used only from the main thread of an application.

  • NSCell and all of its descendants

  • NSView and all of its descendants. For more information, see NSView Restrictions.

Window Restrictions

You can create a window on a secondary thread. The Application Kit ensures that the data structures associated with a window are deallocated on the main thread to avoid race conditions. There is some possibility that window objects may leak in an application that deals with a lot of windows concurrently.

You can create a modal window on a secondary thread. The Application Kit blocks the calling secondary thread while the main thread runs the modal loop.

Event Handling Restrictions

The main thread of the application is responsible for handling events. The main thread is the one blocked in therun method of NSApplication, usually invoked in an application’s main function. While the Application Kit continues to work if other threads are involved in the event path, operations can occur out of sequence. For example, if two different threads are responding to key events, the keys could be received out of order. By letting the main thread process events, you achieve a more consistent user experience. Once received, events can be dispatched to secondary threads for further processing if desired.

You can call the postEvent:atStart: method of NSApplication from a secondary thread to post an event to the main thread’s event queue. Order is not guaranteed with respect to user input events, however. The main thread of the application is still responsible for handling events in the event queue.

Drawing Restrictions

The Application Kit is generally thread-safe when drawing with its graphics functions and classes, including theNSBezierPath and NSString classes. Details for using particular classes are described in the following sections. Additional information about drawing and threads is available in Cocoa Drawing Guide.

NSView Restrictions

The NSView class is generally not thread-safe. You should create, destroy, resize, move, and perform other operations on NSView objects only from the main thread of an application. Drawing from secondary threads is thread-safe as long as you bracket drawing calls with calls to lockFocusIfCanDraw and unlockFocus.

If a secondary thread of an application wants to cause portions of the view to be redrawn on the main thread, it must not do so using methods like displaysetNeedsDisplay:setNeedsDisplayInRect:, orsetViewsNeedDisplay:. Instead, it should send a message to the main thread or call those methods using theperformSelectorOnMainThread:withObject:waitUntilDone: method instead.

The view system’s graphics states (gstates) are per-thread. Using graphics states used to be a way to achieve better drawing performance over a single-threaded application but that is no longer true. Incorrect use of graphics states can actually lead to drawing code that is less efficient than drawing in the main thread.

NSGraphicsContext Restrictions

The NSGraphicsContext class represents the drawing context provided by the underlying graphics system. EachNSGraphicsContext instance holds its own independent graphics state: coordinate system, clipping, current font, and so on. An instance of the class is automatically created on the main thread for each NSWindow instance. If you do any drawing from a secondary thread, a new instance of NSGraphicsContext is created specifically for that thread.

If you do any drawing from a secondary thread, you must flush your drawing calls manually. Cocoa does not automatically update views with content drawn from secondary threads, so you need to call the flushGraphicsmethod of NSGraphicsContext when you finish your drawing. If your application draws content from the main thread only, you do not need to flush your drawing calls.

NSImage Restrictions

One thread can create an NSImage object, draw to the image buffer, and pass it off to the main thread for drawing. The underlying image cache is shared among all threads. For more information about images and how caching works, see Cocoa Drawing Guide.

Core Data Framework

The Core Data framework generally supports threading, although there are some usage caveats that apply. For information on these caveats, see Concurrency with Core Data in Core Data Programming Guide.

Core Foundation

Core Foundation is sufficiently thread-safe that, if you program with care, you should not run into any problems related to competing threads. It is thread-safe in the common cases, such as when you query, retain, release, and pass around immutable objects. Even central shared objects that might be queried from more than one thread are reliably thread-safe.

Like Cocoa, Core Foundation is not thread-safe when it comes to mutations to objects or their contents. For example, modifying a mutable data or mutable array object is not thread-safe, as you might expect, but neither is modifying an object inside of an immutable array. One reason for this is performance, which is critical in these situations. Moreover, it is usually not possible to achieve absolute thread safety at this level. You cannot rule out, for example, indeterminate behavior resulting from retaining an object obtained from a collection. The collection itself might be freed before the call to retain the contained object is made.

In those cases where Core Foundation objects are to be accessed from multiple threads and mutated, your code should protect against simultaneous access by using locks at the access points. For instance, the code that enumerates the objects of a Core Foundation array should use the appropriate locking calls around the enumerating block to protect against someone else mutating the array.

你可能感兴趣的:(Thread Safety Summary)