Skip to content

Thread safe implementation of synchronized in Swift

License

Notifications You must be signed in to change notification settings

brennanMKE/ThreadSafe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ThreadSafe - Thread Safety in Swift

Concurrency in Swift is very tricky. Not only is the language changing regularly, possibly causing working code to break, it has not brought forward useful features from Objective-C which simplified thread safety. One feature in particular in the @synchronized directive which ensures a block of code is thread safe. It is possible to use features like NSLock or DispatchSemaphore but these are not as simple to use as the directive available in Objective-C.

This sample project implements functionality like @synchronized for Swift. It uses DispatchSemaphore to ensure only one instance is executed at a time. It uses a global variable for the semaphore which may not be ideal for a high performant application. For simple cases this solution may be sufficient. Feedback in the form of new Issues or Pull Requests are appreciated.

Why?

Managing code which is running concurrently across different threads or queues is dangerous because values may not be in sync and implementing a concurrency solution risks deadlocking which is hard to track down and fix. That is what made the @synchronized directive in Objective-C so helpful. It made the implementation simple which reduced the risk of values getting out of sync or causing a deadlock.

With optionals and initialization being such an important focus in Swift there are often constructs in place which will require managing a thread safe initialization sequence. It is tempting to use a lazy property, assuming the block is only run once and is thread safe, but it is not. The documentation on Properties notes the following:

If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once.

Since it is not possible to rely on atomic properties it is necessary to ensure that critical properties are managed in a thread safe way. And a reuseable solution allows for relying on a tested solution which is known to work instead of carefully implementing a unique implementation each time it is needed.

Usage

Run a synchronized block which is non-escaping with the code below.

public func work() {
    synchronized {
        // do work here
    }
}

When your closure returns a value you can do so with a variation of the same function.

private func work() {
    synchronized { () -> String in
        // return a value after working
    }
}

Testing

A series of unit tests are included which attempt to break the implementation. Run these unit tests yourself with the version of Swift you are using to ensure that the synchronized functions work as intended.

License

MIT


Brennan Stehling (c) 2017

About

Thread safe implementation of synchronized in Swift

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published