Which is thread Safe atomic or non-atomic? - ios

After reading this answer I am very confused.
Some says atomic is thread safe and some are saying nonatomic is thread safe.
What is the exact answer of this.

Thread unsafety of operations is caused by the fact that an operation can be divided into several suboperations, for example:
a = a + 1
can be subdivided into operations
load value of a
add 1 to the loaded value
assign the calculated value to a.
The word "Atomic" comes from "atom" which comes from greek "atomos", which means "that which can't be split". For an operation it means that it is always performed as a whole, it is never performed one suboperation at a time. That's why it is thread safe.
TL;DR Atomic = thread safe.
Big warning: Having properties atomic does not mean that a whole function/class is thread safe. Atomic properties means only that operations with the given properties are thread safe.

Obviously, nonatomic certainly isn’t thread safe. More interestingly, atomic is closer, but it is insufficient to achieve “thread safety”, as well. To quote Apple’s Programming with Objective-C: Encapsulating Data:
Note: Property atomicity is not synonymous with an object’s thread safety.
It goes on to provide an example:
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.
This example is quite simple, but the problem of thread safety becomes much more complex when considered across a network of related objects. Thread safety is covered in more detail in Concurrency Programming Guide.
Also see bbum’s Objective-C: Atomic, properties, threading and/or custom setter/getter.
The reason this is so confusing is that, in fact, the atomic keyword does ensure that your access to that immediate reference is thread safe. Unfortunately, when dealing with objects, that’s rarely sufficient. First, you have no assurances that the property’s own internal properties are thread safe. Second, it doesn’t synchronize your app’s access to the object’s individual properties (such as Apple’s example above). So, atomic is almost always insufficient to achieve thread safety, so you generally have to employ some higher-level degree of synchronization. And if you provide that higher-level synchronization, adding atomicity to that mix is redundant and inefficient.
So, with objects, atomic rarely has any utility. It can be useful, though, when dealing primitive C data types (e.g. integers, booleans, floats). For example, you might have some boolean that might be updated in some other thread indicating whether that thread’s asynchronous task is completed. This is a perfect use case for atomic.
Otherwise, we generally reach for higher-level synchronization mechanisms for thread safety, such as GCD serial queues or reader-writer pattern (... or, less common nowadays, locks, the #synchronized directive, etc.).

As you can read at developer.apple you should use atomic functions for thread savety.
You can read more about atomic functions here: Atomic Man page
In short:
Atomic ~ not splittable ~ not shared by threads

As is mentioned in several answers to the posted question, atomic is thread safe. This means that getter/setter working on any thread should finish first, before any other thread can perform getter/setter.

Related

How to implement a lock and unlock sequence in a metal shader?

How should I implement a lock/unlock sequence with Compare and Swap using a Metal compute shader.
I’ve tested this sample code but it does not seem to work. For some reason, the threads are not detecting that the lock was released.
Here is a brief explanation of the code below:
The depthFlag is an array of atomic_bools. In this simple example, I simply try to do a lock by comparing the content of depthFlag[1]. I then go ahead and do my operation and once the operation is done, I do an unlock.
As stated above, only one thread is able to do the locking/work/unlocking but the rest of the threads get stuck in the while loop. They NEVER leave. I expect another thread to detect the unlock and go through the sequence.
What am I doing wrong? My knowledge on CAS is limited, so I appreciate any tips.
kernel void testFunction(device float *depthBuffer[[buffer(4)]], device atomic_bool *depthFlag [[buffer(5)]], uint index[[thread_position_in_grid]]){
//lock
bool expected=false;
while(!atomic_compare_exchange_weak_explicit(&depthFlag[1],&expected,true,memory_order_relaxed,memory_order_relaxed)){
//wait
expected=false;
}
//Do my operation here
//unlock
atomic_store_explicit(&depthFlag[1], false, memory_order_relaxed);
//barrier
}
You essentially can't use the locking programming model for GPU concurrency. For one, the relaxed memory order model (the only one available) is not suitable for this; for another, you can't guarantee that other threads will make progress between your atomic operations. Your code must always be able to make progress, regardless of what the other threads are doing.
My recommendation is that you use something like the following model instead:
Read atomic value to check if another thread has already completed the operation in question.
If no other thread has done it yet, perform the operation. (But don't cause any side effects, i.e. don't write to device memory.)
Perform an atomic operation to indicate your thread has completed the operation while checking whether another thread got there first. (e.g. compare-and-swap a boolean, but increasing a counter also works)
If another thread got there first, don't perform side effects.
If your thread "won" and no other thread registered completion, perform your operation's side effects, e.g. do whatever you need to do to write out the result etc.
This works well if there's not much competition, and if the result does not vary depending on which thread performs the operation.
The occasional discarded work should not matter. If there is significant competition, use thread groups; within a thread group, the threads can coordinate which thread will perform which operation. You may still end up with wasted computation from competition between groups. If this is a problem, you may need to change your approach more fundamentally.
If the results of the operation are not deterministic, and the threads all need to proceed using the same result, you will need to change your approach. For example, split your kernels up so any computation which depends on the result of the operation in question runs in a sequentially queued kernel.

Atomic property and usage

I have read many stackoverflow answers for this like Is an atomic property thread safe?, When to use #atomic? or Atomic properties vs thread-safe in Objective-C but I have question for this:
Please correct me If I am wrong, This is like that I am using a count variable which I have declared with Atomic property and currently its value is 5
which is accessed by two thread , First thread that is increasing count value by 2 and 2nd thread decreasing the count value by 1 ,According to my understanding this go sequentially like when first thread increased its value which is now 5 + 2 = 7; after then only 2nd thread can access count variable and only decrease its value by 1 and that is 7 - 1 = 6?
First thread that is increasing count value by 2
That is not an atomic operation, and atomic in no way helps you. This is (at least) three separate atomic operations:
read value
increase value
write value
This is the classic multi-writer race condition. Another thread might read between "read value" and "write value." In your example the final result could be 4, such that the increase operation is completely lost (A reads 5, B reads 5, A +2, A writes 7, B -1, B writes 4).
The problem that atomic is meant to solve is that "read value" and "write value" aren't even atomic operations in many platform-specific situations. The above may actually be 5 operations such as:
read lower word
read upper word
increase value
write lower word
write upper word
Without atomic, another thread might read between "write lower word" and "write upper word" and get a garbage value that was never written (half of one value and half of another). By using atomic, you ensure that readers will always receive a "legitimate" value (one that was written at some point). But that's not much of a promise.
But as is noted in the questions you provide, if you need to make reads and writes atomic, you almost certainly need more than that, because you also want to make "increase the value" atomic. So in practice atomic is rarely useful. If you don't need it, it's slow. If you do need it, it's probably insufficient.
Atomic based property where two threads are accessing same object to increase or decrease a value , You can understand this like both have accessed the same/whole value which is 5 but First thread trying to update this value then this is locked no other thread can update this at the same time however 2nd thread is also having same value which is 5 and can update only when Count object updation get exited by first thread.
Ok, threads might not execute sequentially, the first thread created might run after the second one. If the threads executes in the order you describe, the mentioned behavior is fine. But I think that your have a misconception about thread safe.
I encourage you to read more about Concurrency Programming Guide and Thread safe.

When to use #atomic?

I've already seen this question:
What's the difference between the atomic and nonatomic attributes?
I understand that #atomic does not guarantee thread safe, and I have to use other mechanisms (e.g. #synchronized) to realize that. Based on that, I don't still know EXACTLY when to use #atomic attribute. I'd like to know USE CASE of using #atomic alone.
The typical use-case for atomic properties is when dealing with a primitive data type across multiple threads. For example, let's say you have some background thread doing some processing and you have some BOOL state property, e.g. isProcessComplete and your main thread wants to check to see if the background process is complete:
if (self.isProcessComplete) {
// Do something
}
In this case, declaring this property as atomic allows us to use/update this property across multiple threads without any more complicated synchronization mechanism because:
we're dealing with a scalar, primitive data type, e.g. BOOL;
we declared it to be atomic; and
we're using the accessor method (e.g. self.) rather than accessing the ivar directly.
When dealing with objects or other more complicated situations, atomic generally is insufficient. As you point out, in practice, atomic, alone, is rarely sufficient to achieve thread safety, which is why we don't use it very often. But for simple, stand-alone, primitive data types, atomic can be an easy way to ensure safe access across multiple threads.
#atomic will guarantee You, that the value, that You will receive will not be gibberish. A possible situation is to read a given value from one thread and to set its value from another. Then the #atomic keyword will ensure that You receive a whole value. Important thing to now is that the value that You get is not guaranteed to be the one that has been set most recently.
The second part of the Your question, about the use case is purely circumstantial, depending on the implementation the intentions. For example if You have some kind of time based update on a list every second or so, You could use atomic to ensure that You will get whole values, and the timer that updates Your list can ensure that You will have the latest data on screen or under the hood in some implicit logic.
EDIT: After a remark from #Rob I saw the need of paraphrasing the last part of my answer. In most cases atomic is not enough to get the job done. And there is a need of a better solution, like #synchronized.
atomic guarantees that competing threads will get/set whole values, whether you're setting a primitive type or a pointer to an object. With nonatomic access, it's possible to get a torn read or write, especially if you're dealing with 64-bit values.
atomic also guarantees that an object pointer won't be garbage when you retrieve it:
https://github.com/opensource-apple/objc4/blob/master/runtime/objc-accessors.mm#L58-L61.
That being said, if you're pointing to a mutable object, atomic won't offer you any guarantees about the object's state.
atomic is appropriate if you're dealing with:
Immutable objects
Primitives (like int, char, float)
atomic is inappropriate if:
The object or any of its descendant properties are mutable
If you need thread safety for a primitive value or immutable object, this is one of the fastest ways to guard against torn reads/writes that you can find.

When can I not use atomic properties? [duplicate]

This question already has answers here:
What's the difference between the atomic and nonatomic attributes?
(27 answers)
Closed 7 years ago.
I know there are answers on atomic vs. non-atomic answers, but they mostly seem to be fairly old (2011 and earlier), so I'm hoping for updated advice. My understanding is that non-atomic properties are faster but not thread safe. Does this mean that any property that might be accessed from multiple threads at the same time should always be atomic? Are there conditions that can make it ok to make it non-atomic? What other concerns are there in determining whether to make a property atomic or nonatomic?
Declaring a property atomic makes compiler generate additional code that prevents concurrent access to the property. This additional code locks a semaphore, then gets or sets the property, and then unlock the semaphore. Compared to setting or getting a primitive value or a pointer, locking and unlocking a semaphore is expensive (although it is usually negligible if you consider the overall flow of your app).
Since most of your classes under iOS, especially the ones related to UI, will be used in a single-threaded environment, it is safe to drop atomic (i.e. write nonatomic, because properties are atomic by default), even though the operation is relatively inexpensive, you do not want to pay for things that you do not need.
Declaring a property as atomic does not necessarily make it thread safe.
Atomic is the default and involves some extra overhead compared to nonatomic. If thread A is halfway through the getter for that property and thread B changes the value in the setter, using atomic will ensure that a viable, whole value is returned from the getter. If you use nonatomic no such guarantee is made, the extra code is not generated, and thus nonatomic is faster.
However, This does not guarantee thread safety. If thread A calls the getter and threads B and C are updating the thread with different values then thread A could get either value and there is no guarantee which one it will get.
To specifically answer your question, many scenarios allow for nonatomic properties, if not most. Although the extra overhead of using atomic is probably negligable. Simply put, are your properties read or set on different threads? If not, you most likely don't need to declare them as atomic but the extra overhead might not even be noticable. It's just that simply declaring them as atomic does not guarantee thread safety.
In most situations it is unimportant, whether a property is atomic or not in a multithreaded environment.
What?
In most situations it is unimportant, whether a property is atomic or not in a multithreaded environment.
The reason for this is that making a property "thread-safe" by turning atomicity on does not make your code thread-safe. To get this you need more work and this work typically implicitly ensures that the property is not accessed parallel.
Let's have an example: You have a class Person with the properties firstName and lastName both of NSString*. You simply want to add the both name separated with a space to have a full name.
NSString *fullName = [NSString stringWithFormat:#"%# %#", person.firstName, person.lastName];
You know that other threads can update the properties while you do that. Making the properties atomic doesn't help anything. This does not help, if the last name of the persons are changed, after reading the first name, but before reading the second name. This does not help, if the names of the persons are changed after calculating the full name, because this can be invalid in the very next moment.
You have to serialize operations, not property accesses. But atomicity only serializes accesses. So it does not help, if at least one operation has more than one access. 99,999999373 % of all cases.
Forget about property atomicity. It is meaningless.
There are no other concerns. Yes, any property that can be accessed on multiple threads should be atomic or you can end up with unexpected results.

Atomically read/write int value w/o additional operation on the int value itself

GCC offers a nice set of built-in functions for atomic operations. And being on MacOS or iOS, even Apple offers a nice set of atomic functions. However, all these functions perform an operation, e.g. an addition/subtraction, a logical operation (AND/OR/XOR) or a compare-and-set/compare-and-swap. What I am looking for is a way to atomically assign/read an int value, like:
int a;
/* ... */
a = someVariable;
That's all. a will be read by another thread and it is only important that a either has its old value or its new value. Unfortunately the C standard does not guarantee that assigning or reading a value is an atomic operation. I remember that I once read somewhere, that writing or reading a value to a variable of type int is guaranteed to be atomic in GCC (regardless the size of int) but I searched everywhere on the GCC homepage and I cannot find this statement any longer (maybe it was removed).
I cannot use sig_atomic_t because sig_atomic_t has no guaranteed size and it might also have a different size than int.
Since only one thread will ever "write" a value to a, while both threads will "read" the current value of a, I don't need to perform the operations themselves in an atomic manner, e.g.:
/* thread 1 */
someVariable = atomicRead(a);
/* Do something with someVariable, non-atomic, when done */
atomicWrite(a, someVariable);
/* thread 2 */
someVariable = atomicRead(a);
/* Do something with someVariable, but never write to a */
If both threads were going to write to a, then all operations would have to be atomic, but that way, this may only waste CPU time; and we are extremely low on CPU resources in our project. So far we use a mutex around read/write operations of a and even though the mutex is held for such a tiny amount of time, this already causes problems (one of the threads is a realtime thread and blocking on a mutex causes it to fail its realtime constraints, which is pretty bad).
Of course I could use a __sync_fetch_and_add to read the variable (and simply add "0" to it, to not modify its value) and for writing use a __sync_val_compare_and_swap for writing it (as I know its old value, so passing that in will make sure the value is always exchanged), but won't this add unnecessary overhead?
A __sync_fetch_and_add with a 0 argument is indeed the best bet if you want your load to be atomic and act as a memory barrier. Similarly, you can use an and with 0 or an or with -1 to store 0 and -1 atomically with a memory barrier. For writing, you can use __sync_test_and_set (actually an xchg operation) if an "acquire" barrier is enough, or if using Clang you can use __sync_swap (which is an xchg operation with a full barrier).
However, in many cases that's overkill and you may prefer to add memory barriers manually. If you do not want the memory barrier, you can use a volatile load to atomically read/write a variable that is aligned and no wider than a word:
#define __sync_access(x) (*(volatile __typeof__(x) *) &(x))
(This macro is an lvalue, so you can also use it for a store like __sync_store(x) = 0). The function implements the same semantics as the C++11 memory_order_consume form, but only under two assumptions:
that your machine has coherent caches; if not, you need a memory barrier or global cache flush before the load (or before the first of a group of load).
that your machine is not a DEC Alpha. The Alpha had very relaxed semantics for reordering memory accesses, so on it you'd need a memory barrier after the load (and after each load in a group of loads). On the Alpha the above macro only provides memory_order_relaxed semantics. BTW, the first versions of the Alpha couldn't even store a byte atomically (only a word, which was 8 bytes).
In either case, the __sync_fetch_and_add would work. As far as I know, no other machine imitated the Alpha so neither assumption should pose problems on current computers.
Volatile, aligned, word sized reads/writes are atomic on most platforms. Checking your assembly would be the best way to find out if this is true on your platform. Atomic registers cannot produce nearly as many interesting wait free structures as the more complicated mechanisms like compare and swap, which is why they are included.
See http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.56.5659&rank=3 for the theory.
Regarding synch_fetch_and_add with a 0 argument - This seems like the safest bet. If you're worried about efficiency, profile the code and see if you're meeting your performance targets. You may be falling victim to premature optimization.

Resources