Understanding atomicity - objective-c

Apple documentation says that Atomic operations does not block the competing threads. But, how can it return/set whole value without blocking the competing threads. For example, when Thread 3(T3) is in the middle of getter if both thread1 and thread2 calls setter methods (since does not block competing threads both T1 and T2 are allowed to enter setter method) won't it return invalid value?
I have gone through many web-sites that explain atomicity with example. The examples use #synchronized(self) i setter and getter. Won't #synchronized() allow only single thread to execute a setter at a time blocking other threads?

Related

Is it thread-safe to read an instance variable while calling a setter from another thread?

I have an object with a property:
#interface Car
#property(strong) NSLicensePlate *licensePlate;
#end
I use the property in a method:
- (void) doSomething {
[_licensePlate frobnicate];
}
And the property value can be changed in another method:
- (void) doSomethingElse {
[self setLicensePlate:[_licensePlateDealer cleanLicensePlate]];
}
Now, if the -doSomethingElse method is called from another thread while I access the license plate property using the instance variable (as seen in the -doSomething method), is it possible to get a segfault?
Is it possible that the -setLicensePlate setter releases the value stored in _licensePlate right before I call -frobnicate on it and before a new valid value is assigned? And would it help to call [self licensePlate] instead of using _licensePlate directly?
If you want to enjoy the atomic behavior (which is the default behavior that you get because you didn't specify the nonatomic qualifier) of this property, you must use the getter (self.licensePlate or [self licensePlate]), not use the ivar (_licensePlate).
In general, it's usually prudent to use the getters and setters everywhere except (a) the init method; and (b) and custom accessor methods. The overhead is negligible and you avoid spectrum of potential problems ranging from atomicity, memory semantics, KVO, future-proofing code in case you customize accessor methods at some future date, etc.
But, assuming you access your property only through the accessor methods (the getters and setters), the atomic qualifier, as described by Programming with Objective-C: Encapsulating Data ensures that the pointer, itself, that you are retrieving/setting is will not be corrupted by another thread:
[Atomic] means that the synthesized accessors ensure that a value is always fully retrieved by the getter method or fully set via the setter method, even if the accessors are called simultaneously from different threads.
In answer to your question, if the other thread changes the licensePlate property, while the frobnicate method is running on the other thread, that original object will not be released until that method returns.
But to be clear, the atomic qualifier does not ensure thread safety. As the above guide goes on to warn us:
Note: Property atomicity is not synonymous with an object’s thread safety.
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.
So, it might be thread-safe to use frobnicate on one thread while doing other stuff on another thread, but it also might not. It depends upon all the different things that can be done with this license plate object. Because the protections offered by atomic are so minimalist, we frequently will employ some synchronization (via GCD serial queue or GCD reader-writer pattern, or via any of the synchronization methods outlined in the Threading Programming Guide: Synchronization such as locks) to coordinate interaction from different threads.
When you define properties, you can set them as atomic (the default) or nonatomic.
Since you're using the atomic default, you should be fine about thread safety, but that also depends on how you implemented frobnicate, setLicensePlate: and cleanLicensePlate.
Please refer to this question to get more details about atomic vs nonatomic: What's the difference between the atomic and nonatomic attributes?

Does #synchronize protect Objects that are pointed to by other Objects?

For example let's say we have objectA, which points to ObjectB, which points to objectC.
We then do
#synchronized(objectA) {
[self doSomeStuff];
}
What is protected here from other threads? Just objectA, or objectB and objectC and anything that any object references all the way down?
#synchronized(obj) {...} merely means that whatever is in the {...} will not be executed concurrently with any other #synchronized(obj)'s {...}.
I.e. given:
thread 1:
#synchronized(objectA) {
[self doSomeStuff];
}
thread 2:
#synchronized(objectA) {
[self doSomeStuff];
}
thread 3:
[self doSomeStuff];
One of thread 1 or thread 2 will block while the other executes doSomeStuff, but thread 3 will merrily invoke doSomeStuff concurrently.
And, more directly to your question, that implies that, no, there is absolutely zero concurrency protection for anything that doSomeStuff might do internally.
If you want your objects to be "thread safe", they need to be designed from top to bottom with concurrency in mind (and that does not generally mean with tons of locks or synchronization primitives everywhere).
#synchronized(objectA) creates critical section. In your example it guarantees, that [self doSomeStuff] will not be executed simultaneously by different threads.
objectA is used just to identify which implicitly created recursive lock will be used. Critical sections, created by #synchronized directive with same object as argument will not be executed simultaneously.
From Apple documentation:
The #synchronized directive is a convenient way to create mutex locks
on the fly in Objective-C code. The #synchronized directive does what
any other mutex lock would do—it prevents different threads from
acquiring the same lock at the same time. In this case, however, you
do not have to create the mutex or lock object directly. Instead, you
simply use any Objective-C object as a lock token
The object passed to the #synchronized directive is a unique
identifier used to distinguish the protected block. If you execute the
preceding method in two different threads, passing a different object
for the anObj parameter on each thread, each would take its lock and
continue processing without being blocked by the other. If you pass
the same object in both cases, however, one of the threads would
acquire the lock first and the other would block until the first
thread completed the critical section.

Can I safely use 'nonatomic' ivars within a dispatch_barrier of a customized concurrent queue?

Is it safe to access non-atomic ivars from within a dispatch_barrier of a customized-concurrent queue?
The following code snippet is an abridged version of method using a dispatch barrier:
- (void)cacheData:(NSData *)data toFile:(NSString *)fileName {
dispatch_barrier_async(concurrentQueue, ^{
[_memoryCache setObject:data forKey:fileName];
// ...
}
});
}
I want to get a basic understanding of the non-atomic thread safety (i.e., without the overhead of using atomic vs non-atomic iVars).
This concerns Swift as will as Objective-C.
Atomic ≠ Thread safe
In order to answer this, let's first split the read/write operations into 3 distinct categories:
Direct Writes: When you directly set a variable/property to a given value. For example:
yourDictionary = [NSMutableDictionary dictionary];
Indirect Writes: When you mutate the object itself by changing a variable on it. For example:
[yourDictionary setObject:#"foo" forKey:#"bar"];
Reads: When you do any form of passive reading from an object (when the reading doesn't lead to any changes to the object itself). For example:
NSString* foo = [yourDictionary objectForKey:#"bar"];
So what does the atomic attribute on properties (you cannot set this on an ivar directly) ensure?
It ensures that direct writes and reads are serialised. However, it does nothing to protect the object from being indirectly written to while being read from another thread, which is unsafe.
Therefore, atomic properties make the most amount of sense with immutable objects (such as NSString, NSDictionary & NSArray). Once these objects are set, you cannot mutate them, and therefore are thread safe when atomic.
See here for full a list of the thread safe immutable objects.
If you want to use the atomic attribute on a mutable object, you will have still to ensure yourself that indirect writes and reads are serialised correctly.
What does the nonatomic attribute ensure?
Nothing.
No serialisation will take place for direct writes, indirect writes and reads. As a consequence, it is faster. However it is completely up to you to ensure that reads and writes are serialised correctly.
So how do I serialise read and writes?
You are indeed correct in approaching this by using a concurrent GCD queue. GCD queues don't impose some of the costs that traditional locks bring with them.
So, if you're looking to do this on a nonatomic ivar, you'll need to serialise the direct writes, indirect writes and reads. If you were doing this on an atomic property, you'd only need to serialise the indirect writes and reads.
As you have in your question, you should use a dispatch_barrier on your concurrent queue in order to make any writes (direct or indirect).
This is because a dispatch_barrier will wait until all tasks on the concurrent queue have been completed before preceding, and will block any further tasks from taking place until it has completed. Therefore the writes will take place without any interruptions from other writes or reads, while multiple reads can take place concurrently
You should therefore also channel any reads of the object through your concurrent queue as well, using a dispatch_sync. You shouldn't have to use a barrier for your reads, as multiple reads from different threads shouldn't cause a problem.
I hope this clarifies the issue for you.
TL;DR
Yes, your approach appears to be correct.

How to end a polling thread created with detachNewThreadSelector?

I'm creating a new thread using detachNewThreadSelector ref with toTarget self.
The purpose of the thread is to poll movements and load images as appropriate - it loops and only quits when an atomic bool is set to true in the main thread - which is set in the objects dealloc.
The problem is caused by this (from the detachNewThreadSelector reference):
The objects aTarget and anArgument are retained during the execution of the detached thread, then released
Which means my object will always have a (minimum) retain count of one - because the thread continuously polls. dealloc is therefore never called.
So my question is: how can I dealloc my object taking into account the existence of the polling thread?
The only idea I have right now is to create a destroyThread function of the object, which sets the end thread bool, which would be called from everywhere I'd expect the object to be destroyed. This seems error-prone, are there better solutions?
Thanks in advance.
Update
I had an idea for another solution - in the thread I detect if the retain count is one - if it's one then I know the thread is keeping the object alive, so I break the loop and dealloc is called. Is this a robust solution?
First, avoid detachNewThreadSelector:. Anything you are thinking of doing with it is almost certainly done better with a dispatch queue or NSOperationQueue. Even if you need to manually create a thread (which is exceedingly rare in modern ObjC), it is better to create explicit NSThread objects and hold onto them rather than using detachNewThreadSelector: which creates a thread you can't interact directly with anymore.
To the specific question, if you create your own threads, then you'll need to set that bool somewhere other than dealloc. That means that some other part of the program needs to tell you to shut down. You can't just be released and automatically clean yourself up using manual threads this way.
EDIT: Never, ever call retainCount. No solution involving retainCount is a good solution. Putting aside the various practical problems with using retainCount in more general cases, in this case it ties you manual reference counting. You should switch to ARC as quickly as possible, and retainCount is illegal in ARC (it should have been illegal before ARC, but they finally had a really good excuse to force the issue). If you can't implement your solution in ARC, it is unlikely a good solution.
Again, the best solution is to use GCD dispatch queues (or operations, which are generally implemented with dispatch queues). It is incredibly more efficient and effective for almost every problem than manual thread management.
If you must use a manual thread for legacy code and need to maintain this kind of auto-destruct, the solution is a helper object that owns the thread. Your object owns the helper object, which has a retain loop with the thread. When your object is deallocated, then it tells the thread to shut down, which breaks the retain loop, and the helper object goes away. This is a standard way of managing retain loops.
See Apple's Migrating Away From Threads for more.

What does #synchronized() do as a singleton method in objective C?

I just created a singleton method, and I would like to know what the function #synchronized() does, as I use it frequently, but do not know the meaning.
It declares a critical section around the code block. In multithreaded code, #synchronized guarantees that only one thread can be executing that code in the block at any given time.
If you aren't aware of what it does, then your application probably isn't multithreaded, and you probably don't need to use it (especially if the singleton itself isn't thread-safe).
Edit: Adding some more information that wasn't in the original answer from 2011.
The #synchronized directive prevents multiple threads from entering any region of code that is protected by a #synchronized directive referring to the same object. The object passed to the #synchronized directive is the object that is used as the "lock." Two threads can be in the same protected region of code if a different object is used as the lock, and you can also guard two completely different regions of code using the same object as the lock.
Also, if you happen to pass nil as the lock object, no lock will be taken at all.
From the Apple documentation here and here:
The #synchronized directive is a
convenient way to create mutex locks
on the fly in Objective-C code. The
#synchronized directive does what any
other mutex lock would do—it prevents
different threads from acquiring the
same lock at the same time.
The documentation provides a wealth of information on this subject. It's worth taking the time to read through it, especially given that you've been using it without knowing what it's doing.
The #synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code.
The #synchronized directive does what any other mutex lock would do—it prevents different threads from acquiring the same lock at the same time.
Syntax:
#synchronized(key)
{
// thread-safe code
}
Example:
-(void)AppendExisting:(NSString*)val
{
#synchronized (oldValue) {
[oldValue stringByAppendingFormat:#"-%#",val];
}
}
Now the above code is perfectly thread safe..Now Multiple threads can change the value.
The above is just an obscure example...
#synchronized block automatically handles locking and unlocking for you. #synchronize
you have an implicit lock associated with the object you are using to synchronize. Here is very informative discussion on this topic please follow How does #synchronized lock/unlock in Objective-C?
Excellent answer here:
Help understanding class method returning singleton
with further explanation of the process of creating a singleton.
#synchronized is thread safe mechanism. Piece of code written inside this function becomes the part of critical section, to which only one thread can execute at a time.
#synchronize applies the lock implicitly whereas NSLock applies it explicitly.
It only assures the thread safety, not guarantees that. What I mean is you hire an expert driver for you car, still it doesn't guarantees car wont meet an accident. However probability remains the slightest.