Locks, Thread Safety, and Swift: 2017 Edition
Note that
pthread_mutex_t
,pthread_rwlock_t
, andos_unfair_lock
are value types, not reference types. That means that if you use=
on them, you make a copy. This is important, because these types can’t be copied! If you copy one of thepthread
types, the copy will be unusable and may crash when you try to use it. Thepthread
functions that work with these types assume that the values are at the same memory addresses as where they were initialized, and putting them somewhere else afterwards is a bad idea.os_unfair_lock
won’t crash, but you get a completely separate lock out of it which is never what you want.If you use these types, you must be careful never to copy them, whether explicitly with a
=
operator, or implicitly by, for example, embedding them in astruct
or capturing them in a closure.Additionally, since locks are inherently mutable objects, this means you need to declare them with
var
instead oflet
.[…]
You must be careful with the
pthread
locks, because you can create a value using the empty()
initializer, but that value won’t be a valid lock. These locks must be separately initialized usingpthread_mutex_init
orpthread_rwlock_init
[…]
Previously: Locks, Thread Safety, and Swift, OSSpinLock Is Unsafe, os_unfair_lock.
Update (2018-07-31): Vadim Bulavin (via Andy Bargh):
In this article we will benchmark performance of most notable Apple locking APIs and suggest best options based on their characteristics.
[…]
Based on the benchmark results,
DispatchQueue
must be your best choice for creating a critical section in your code.Under 10000 calculations it performs almost identical to locks, while providing higher-level and thus less error-prone API.