Thread Safety

What Is "Thread Safe"?

An API, object, or data is "thread-safe" when it is safe to manipulate that entity from multiple threads.

This can be due to the nature of the data and how it is manipulated (e.g., it is manipulated with a processor instruction that its guaranteed to be atomic), or more commonly due to the presence of a lock. A lock serialises access to the data, ensuring that only one thread can manipulate it at a time.

When a thread wants to manipulate the data, it acquires the lock - blocking if necessary until the lock is free. When the thread has finished manipulating the data, it releases the lock and allows it to be acquired by other threads.

Implications

If an object is thread-safe, it is OK to access that object from multiple threads without explicit locking. In other words, the object or the API used to access it performs its own locking as necessary to maintain the object's consistency.

If an object is not thread-safe, it is not OK to access that object from multiple threads at once without locking. In fact, it may not be OK to access that object from any thread but the main thread, since the object may be accessed without locking internally to APIs whose locking behaviour a third-party developer cannot control.

There is a third state that's hard to name but easy to describe: An object may not be thread-safe, but may be safe to access from a single thread at once regardless of what that thread is when appropriate locking is used. This is the case if the object's lifecycle and use is controlled by whoever instantiated the object, or if there some other way to share a locking mechanism among all users of the object.

Restrictions

Although many APIs present in Mac OS X are thread-safe, this feature is most thoroughly supported by the BSD-levels of the system (e.g., malloc, fopen, printf, etc).

Intermediate-level APIs such as OpenGL or Quartz are thread-safe, but typically only within a single "context". I.e., multiple threads may call OpenGL/Quartz simultaneously, provided each thread is drawing to its own context.

User-interface frameworks such as Carbon and Cocoa often require that they be invoked from the main thread, and typically do not allow user interface elements to be manipulated from secondary threads. For Carbon APIs, the "Mac OS X threading:" comment within the appropriate header file will indicate if an API is safe to use from outside the main thread.