2
votes

I was reading about thread safe property in iOS. One question I come across:

This question is not regarding how to implement thread safe property, but rather why and why not.

Why don't we make every property of class thread safe normally so that we don't need to worry about thread safety? Is it good to make every property of a class thread safe or will it impact application performance, so not good idea, unless explicitly required?

2

2 Answers

4
votes

This is a great question. There are two major reasons, in my mind.

First, we could make every property atomic by default, and indeed this is the case for Objective-C @propertys. However, if you read most Objective-C, most @property declarations explicitly override the default and make the property nonatomic. Making a property atomic adds a small but potentially significant overhead to accesses to that property, which has performance implications. Most properties don't need to be atomic, so you avoid the performance penalty by making them nonatomic. In Swift, properties are nonatomic by default, and there's no built in way to make them nonatomic.

The second is that making every property "thread safe" (by which I assume you mean atomic), does not ensure that the overall class/struct was thread-safe, and certainly doesn't make even higher level constructs thread-safe. Thread safety is a complicated problem that can't be solved solely at the level of individual property. If the language claimed that properties were thread safe by default, that would likely lull developers, particularly newer ones, into a false sense of security, making them more likely to assume they don't need to worry about thread safety and writing buggy multithreading code as a result.

Instead, property-level atomicity is only one tool in a big toolbox needed to write effective, high-performance, correct multithreaded APIs. Apple (IMO rightly) thinks programmers should really understand the whole problem they're trying to solve and solve it with their own code.

(This is not to preclude future improvements to Swift that do make safe multithreading easier. There are a bunch of things that could -- and hopefull will -- be done to make multithreading easier.)

2
votes

One of the most important requirements implied by "thread safety" is to ensure that the action of one thread, operating on some shared data, can never cause other threads to see the same data in an inconsistent or invalid state.

But, what does "inconsistent or invalid" mean? Only the application developer can say for sure. Often it has to do with relationships between different properties of a single object and/or relationships between different objects.

@Andrew Madsen suggested that making individual properties "atomic" might not be enough. Here's why not:

Suppose that thread A must change three different properties, p1, p2, and p3, in order to do its job; and suppose that thread B needs to look at those same properties. Making an individual property "atomic" ensures that thread B is guaranteed to see either the "before" value or the "after" value when it looks at any given property. It will never see any other value.

But that may not be enough to ensure thread safety. What happens if thread B sees the "before" value of p1, but the "after" values of p2 and p3? In some programs, that could cause thread B to compute a wrong result, store bad data, or even crash the program.

What needs to be "atomic" is the entire operation that thread A performs. We need to ensure that thread B either sees the "before" values of all three properties, or the "after" values of all three, and never anything else.

We implement that guarantee by ensuring that thread A never does its job except when it has a certain mutex locked, and we must also ensure that thread B never looks at those properties unless it has locked the same mutex.