33
votes

In most of the discussions I've read, it indicates that making a property atomic does not guarantee it to be thread-safe, it just guarantees that the value returned won't be garbage as a result of one object writing to it and another trying to read it at the same time.

I understand this isn't thread-safe as a third object could be writing it and while the object accessing it wouldn't get garbage back, it's not entirely certain which value it will get back as multiple objects are writing to it at the same time, and it may get any of their values.

So when we say it won't return garbage, would garbage be in the sense that if an object was non-atomic and an object tried to access it while another was writing to it, it might get the result back mid-write, and only get a partial, incomplete version of the change brought about by the write? Is this what "garbage" means in this sense, and what atomic properties help to prevent?

5
The thing about "thread safe" is that nothing, by itself, is "thread safe". "Thread safe" can only really be determined in a given context where "thread safe" means that correct operation of the entire context is assured in spite of any possible multi-threading. A particular implementation of a mutable array, say, can maybe said to be "thread safe" in a vacuum, since one will never access internally inconsistent data, but that's meaningless if it's entries are not maintained in synchronization with the external data it references. And that synchronization can only be maintained externally.Hot Licks
@doug-smith You'll likely find my answer on this question + the comments the followed to be helpful. stackoverflow.com/questions/588866/…bbum

5 Answers

44
votes

An atomic property in Objective C guarantees that you will never see partial writes. When a @property has the attribute atomic it is impossible to only partially write the value. The setter is like that:

- (void)setProp:(NSString *)newValue {
    [_prop lock];
    _prop = newValue;
    [_prop unlock];
}

So if two threads want to write the value @"test" and @"otherTest" at the same time, then at any given time the property can only be the initial value of the property or @"test" or @"otherTest". nonatomic is faster but the value is a garbage value and no partial String of @"test"/@"otherTest" (thx @Gavin) or any other garbage value.

But atomic is only thread-safe with simple use. It is not garantueed. Appledoc says the following:

Consider an XYZPerson object in which both a person’s first and last names are changed using atomic accessors from one thread. If another thread accesses both names at the same time, the atomic getter methods will return complete strings (without crashing), but there’s no guarantee that those values will be the right names relative to each other. If the first name is accessed before the change, but the last name is accessed after the change, you’ll end up with an inconsistent, mismatched pair of names.

I never had a problem using atomic at all. I designed the code that way, that there is not problem with atomic properties.

6
votes

In answer to your third paragraph; essentially yes. An atomic number can't be read while a thread is writing the number.

For example, if a thread has written the first two bytes of an atomic four byte number, and a read of that number is requested on another thread, that read has to wait until all four bytes have been written.

Conversely, if a thread has written the first two bytes of a non-atomic four byte number, and a read of that number is requested on another thread at that moment, it will read the first two new data bytes, but will get old data from a previous write operation in the other two bytes.

4
votes

Robert Harvey's answer is correct, but there is a sub-case of that to consider that people often miss. Consider this code: http://pastebin.com/S7XyJm6G

As well as preventing you from reading partially written values, atomic properties also prevent you from getting objects back that you don't control the lifetime of (they do this by retaining and then autoreleasing the object). This is important in single threaded code like the example that I linked, but even more important in multithreaded code where another thread could cause the object to be released out from under you.

0
votes

In concurrent programing:

atomic means if a property value being accessed for writing operation in some thread(thread # 1) and other thread(thread # 2) tries to access the atomic value either for read or write operation then other thread(thread # 2) waits until thread # 1 completes its task. In other words atomic synchronize the access of property on first come first serve basis.

non atomic means if a property value being accessed for writing operation in some thread(thread # 1) and other thread(thread # 2) tries to access the non atomic value either for read or write operation then other thread(thread # 2) gets value immediately gets old value

0
votes

Explicit implementation of

@property (atomic, retain) NSNumber *count

would be like this

- (NSNumber *)count {
    NSNumber *count;
    @synchronized(self) {
        count = [_count retain]; // +1
    }
    return [count autorelease]; // delayed -1
}

- (void)setCount:(NSNumber *)count {
    id oldValue;
    @synchronized(self) {
        oldValue = _count;
        _count = [count retain];
    }
    [oldValue release];
}

Atomic is the default behaviour for a property.An atomic property adds a level of thread safety when getting or setting values. That is, the getter and setter for the property will always be fully completed regardless of what other threads are doing. these properties will be a little slower to access than a nonatomic equivalent.

And explicitly we would implement

@property (nonatomic, retain) NSNumber *count

like this

- (NSNumber *)count {
    return _count;
}

- (void)setCount:(NSNumber *)count {
    if (count != _count) {
        id oldValue = _count;
        _count = [count retain];
        [_oldValue release];
    }
}

Nonatomic properties are not thread safe, and will return their properties directly. This will be faster than atomic properties, but obviously carries some risk if precautions aren’t made.

setter & getter for these Nonatomic property