Changing the locking object inside #synchronized section - objective-c

Can I do any of the following? Will they properly lock/unlock the same object? Why or why not? Assume there are many identical threads using global variable "obj", which was initialized before all threads started.
1.
#synchronized(obj) {
[obj release];
obj = nil;
}
2.
#synchronized(obj) {
obj = [[NSObject new] autorelease];
}

Short answer: no, they won't properly lock/unlock, and such approaches should be avoided.
My first question is why you'd want to do something like this, since these approaches nullify the purposes and benefits of using a #synchronized block in the first place.
In your second example, once a thread changes the value of obj, every subsequent thread that reaches the #synchronized block will synchronize on the new object, not the original object. For N threads, you'd be explicitly creating N autoreleased objects, and the runtime may create up to N recursive locks associated with those objects. Swapping out the object on which you synchronize within the critical section is a fundamental no-no of thread-safe concurrency. Don't do it. Ever. If multiple threads can safely access a block concurrently, just omit the #synchronized entirely.
In your first example, the results may be undefined, and certainly not what you want, either. If the runtime only uses the object pointer to find the associated lock, the code may run fine, but synchronizing on nil has no perceptible effect in my simple tests, so again you're using #synchronized in a pointless way, since it offers no protection whatsoever.
I'm honestly not trying to be harsh, since I figure you're probably just curious about the construct. I'm just wording this strongly to (hopefully) prevent you and others from writing code that is fatally flawed, especially if under the assumption that it synchronizes properly. Good luck!

Related

Thoughts in accessing read only objects from different threads

Based on a previous discussion I had in SO (see Doubts on concurrency with objects that can be used multiple times like formatters), here I'm asking a more theoretical question about objects that during the application lifetime are created once (and never modified, hence read-only) and they can be accessed from different threads. A simple use case it's the Core Data one. Formatters can be used in different threads (main thread, importing thread, etc.).
NSFormatters, for example, are extremely expensive to create. Based on that they can created once and then reused. A typical pattern that can be follow (also highlighted by #mattt in NSFormatter article) is the following.
+ (NSNumberFormatter *)numberFormatter {
static NSNumberFormatter *_numberFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_numberFormatter = [[NSNumberFormatter alloc] init];
[_numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
});
return _numberFormatter;
}
Even if I'm sure that is a very good approach to follow (a sort of read-only/immutable object is created), formatters are not thread safe and so using them in a thread safe manner could be dangerous. I found a discussion on the argument in NSDateFormatter crashes when used from different threads where the author has noticed that a crash could happen.
NSDateFormatters are not thread safe; there was a background thread
attempting to use the same formatter at the same time (hence the
randomness).
So, what could be the problem in accessing a formatter from different threads? Any secure pattern to follow?
Specific answer for formatters:
Prior to iOS 7/OSX 10.9, even read-only access to formatters was not thread-safe. ICU has a ton of lazy computation that it does in response to requests, and that can crash or produce incorrect results if done concurrently.
In iOS 7/OSX 10.9, NSDateFormatter and NSNumberFormatter use locks internally to serialize access to the underlying ICU code, preventing this issue.
General answer:
Real-only access/immutable objects are indeed generally thread-safe, but it's difficult-to-impossible to tell which things actually are internally immutable, and which ones are merely presenting an immutable interface to the outside world.
In your own code, you can know this. When using other people's classes, you'll have to rely on what they document about how to use their classes safely.
(edit, since an example of serializing access to formatters was requested)
// in the dispatch_once where you create the formatter
dispatch_queue_t formatterQueue = dispatch_queue_create("date formatter queue", 0);
// where you use the formatter
dispatch_sync(formatterQueue, ^{ (do whatever you wanted to do with the formatter) });
I'm asking a more theoretical question about objects that during the application lifetime are created once (and never modified, hence read-only)
That is not technically correct: in order for an object to be truly read-only, it must also be immutable. For example, one could create NSMutableArray once, but since the object allows changes after creation, it cannot be considered read-only, and is therefore unsafe for concurrent use without additional synchronization.
Moreover, logically immutable object could have mutating implementation, making them non-thread-safe. For example, objects that perform lazy initialization on first use, or cache state in their instance variables without synchronization, are not thread-safe. It appears that NSDateFormatter is one such class: it appears that you could get a crash even when you are not calling methods to mutate the state of the class.
One solution to this could be using thread-local storage: rather than creating one NSDateFormatter per application you would be creating one per thread, but that would let you save some CPU cycles as well: one report mentions that they managed to shave 5..10% off their start-up time by using this simple trick.

Locking an object from being accessed by multiple threads - Objective-C

I have a question regarding thread safety in Objective-C. I've read a couple of other answers, some of the Apple documentation, and still have some doubts regarding this, so thought I'd ask my own question.
My question is three fold:
Suppose I have an array, NSMutableArray *myAwesomeArray;
Fold 1:
Now correct me if I'm mistaken, but from what I understand, using #synchronized(myAwesomeArray){...} will prevent two threads from accessing the same block of code. So, basically, if I have something like:
-(void)doSomething {
#synchronized(myAwesomeArray) {
//some read/write operation on myAwesomeArray
}
}
then, if two threads access the same method at the same time, that block of code will be thread safe. I'm guessing I've understood this part properly.
Fold 2:
What do I do if myAwesomeArray is being accessed by multiple threads from different methods?
If I have something like:
- (void)readFromArrayAccessedByThreadOne {
//thread 1 reads from myAwesomeArray
}
- (void)writeToArrayAccessedByThreadTwo {
//thread 2 writes to myAwesomeArray
}
Now, both the methods are accessed by two different threads at the same time. How do I ensure that myAwesomeArray won't have problems? Do I use something like NSLock or NSRecursiveLock?
Fold 3:
Now, in the above two cases, myAwesomeArray was an iVar in memory. What if I have a database file, that I don't always keep in memory. I create a databaseManagerInstance whenever I want to perform database operations, and release it once I'm done. Thus, basically, different classes can access the database. Each class creates its own instance of DatabaseManger, but basically, they are all using the same, single database file. How do I ensure that data is not corrupted due to race conditions in such a situation?
This will help me clear out some of my fundamentals.
Fold 1
Generally your understanding of what #synchronized does is correct. However, technically, it doesn't make any code "thread-safe". It prevents different threads from aquiring the same lock at the same time, however you need to ensure that you always use the same synchronization token when performing critical sections. If you don't do it, you can still find yourself in the situation where two threads perform critical sections at the same time. Check the docs.
Fold 2
Most people would probably advise you to use NSRecursiveLock. If I were you, I'd use GCD. Here is a great document showing how to migrate from thread programming to GCD programming, I think this approach to the problem is a lot better than the one based on NSLock. In a nutshell, you create a serial queue and dispatch your tasks into that queue. This way you ensure that your critical sections are handled serially, so there is only one critical section performed at any given time.
Fold 3
This is the same as Fold 2, only more specific. Data base is a resource, by many means it's the same as the array or any other thing. If you want to see the GCD based approach in database programming context, take a look at fmdb implementation. It does exactly what I described in Fold2.
As a side note to Fold 3, I don't think that instantiating DatabaseManager each time you want to use the database and then releasing it is the correct approach. I think you should create one single database connection and retain it through your application session. This way it's easier to manage it. Again, fmdb is a great example on how this can be achieved.
Edit
If don't want to use GCD then yes, you will need to use some kind of locking mechanism, and yes, NSRecursiveLock will prevent deadlocks if you use recursion in your methods, so it's a good choice (it is used by #synchronized). However, there may be one catch. If it's possible that many threads will wait for the same resource and the order in which they get access is relevant, then NSRecursiveLock is not enough. You may still manage this situation with NSCondition, but trust me, you will save a lot of time using GCD in this case. If the order of the threads is not relevant, you are safe with locks.
As in Swift 3 in WWDC 2016 Session Session 720 Concurrent Programming With GCD in Swift 3, you should use queue
class MyObject {
private let internalState: Int
private let internalQueue: DispatchQueue
var state: Int {
get {
return internalQueue.sync { internalState }
}
set (newValue) {
internalQueue.sync { internalState = newValue }
}
}
}
Subclass NSMutableArray to provide locking for the accessor (read and write) methods. Something like:
#interface MySafeMutableArray : NSMutableArray { NSRecursiveLock *lock; } #end
#implementation MySafeMutableArray
- (void)addObject:(id)obj {
[self.lock lock];
[super addObject: obj];
[self.lock unlock];
}
// ...
#end
This approach encapsulates the locking as part of the array. Users don't need to change their calls (but may need to be aware that they could block/wait for access if the access is time critical). A significant advantage to this approach is that if you decide that you prefer not to use locks you can re-implement MySafeMutableArray to use dispatch queues - or whatever is best for your specific problem. For example, you could implement addObject as:
- (void)addObject:(id)obj {
dispatch_sync (self.queue, ^{ [super addObject: obj] });
}
Note: if using locks, you'll surely need NSRecursiveLock, not NSLock, because you don't know of the Objective-C implementations of addObject, etc are themselves recursive.

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.

Risks of using performSelectorInBackground?

I have been doing some testing with ObjectiveResource (iOS->Rails bridge). Things seem to work, but the library is synchronous (or maybe not, but the mailing list that supports it is a mess).
I'm wondering what the pitfalls are to just running all calls in a performSelectorInBackground... in small tests it seems to work fine, but that's the case with many things that are wrong.
The only caveat I've noticed is that you have to create an Autorelease Pool in the method called by performSelectorInBackground (and then you should only call drain and not release?).
performSelectorInBackground: uses threads behind the scenes, and the big thing with threads is that any piece of code touched by more than one is a minefield for race conditions and other subtle bugs. This obviously means drawing to the screen is off-limits outside the main thread. But there are a lot of other libraries that are also not threadsafe, and any code using those is also tainted.
Basically, thread-safety is something you have to intentionally put in your code or it's probably not there. ObjectiveResource doesn't make any claims to it, so already I would be nervous. Glancing at the source, it looks like it mainly uses the Foundation URL loading machinery, which is threadsafe IIRC. But the ObjectiveResource code itself is not. Just at a glance, all of the class methods use static variables, which means they're all subject to race conditions if you performSelectorInBackground: more than once with code that uses them.
It looks like the 1.1 branch on their Github has explicit support for async through a ConnectionManager class. Probably better off using that (though this is essentially unmaintained code, so caveat emptor).
So are you actually experiencing any issues? Or are you just anticipating them?
Running on a background thread shouldn't give you any issues, unless you try to update a UI element from that same background thread. Be sure to forward any UI-related activities to the main thread. For example (pseudo):
- (void)viewWillAppear:(BOOL)animated {
[self performSelectorInBackground:#selector(refreshTableView)];
[super viewWillAppear:animated];
}
- (void)refreshTableView {
// Where _listOfObjects is used to populate your UITableView
#synchronized(self) {
self._listOfObjects = [MyDataType findAllRemote];
}
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
Note also (as above) that if you are changing the value of any instance variables on the background thread, it's important that you synchronize on self to prevent any other threads (like the main thread) from accessing objects in the _listOfObjects array while it is being updated or set. (Or you may "get" an incomplete object.)
I'm not 100% positive (comments are welcome), but I believe that if you declare the _listOfObjects property as atomic, you won't need to worry about the synchronized block. Though, you would need the synchronized block regardless of the #property declaration if, instead of reassigning the value of the property, you were instead making changes to a single, persistent instance. (Eg. Adding/removing objects from a static NSMutableArray.)

iPhone use of mutexes with asynchronous URL requests

My iPhone client has a lot of involvement with asynchronous requests, a lot of the time consistently modifying static collections of dictionaries or arrays. As a result, it's common for me to see larger data structures which take longer to retrieve from a server with the following errors:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSCFArray: 0x3777c0> was mutated while being enumerated.'
This typically means that two requests to the server come back with data which are trying to modify the same collection. What I'm looking for is a tutorial/example/understanding of how to properly structure my code to avoid this detrimental error. I do believe the correct answer is mutexes, but I've never personally used them yet.
This is the result of making asynchronous HTTP requests with NSURLConnection and then using NSNotification Center as a means of delegation once requests are complete. When firing off requests that mutate the same collection sets, we get these collisions.
There are several ways to do this. The simplest in your case would probably be to use the #synchronized directive. This will allow you to create a mutex on the fly using an arbitrary object as the lock.
#synchronized(sStaticData) {
// Do something with sStaticData
}
Another way would be to use the NSLock class. Create the lock you want to use, and then you will have a bit more flexibility when it comes to acquiring the mutex (with respect to blocking if the lock is unavailable, etc).
NSLock *lock = [[NSLock alloc] init];
// ... later ...
[lock lock];
// Do something with shared data
[lock unlock];
// Much later
[lock release], lock = nil;
If you decide to take either of these approaches it will be necessary to acquire the lock for both reads and writes since you are using NSMutableArray/Set/whatever as a data store. As you've seen NSFastEnumeration prohibits the mutation of the object being enumerated.
But I think another issue here is the choice of data structures in a multi-threaded environment. Is it strictly necessary to access your dictionaries/arrays from multiple threads? Or could the background threads coalesce the data they receive and then pass it to the main thread which would be the only thread allowed to access the data?
If it's possible that any data (including classes) will be accessed from two threads simultaneously you must take steps to keep these synchronized.
Fortunately Objective-C makes it ridiculously easy to do this using the synchronized keyword. This keywords takes as an argument any Objective-C object. Any other threads that specify the same object in a synchronized section will halt until the first finishes.
-(void) doSomethingWith:(NSArray*)someArray
{
// the synchronized keyword prevents two threads ever using the same variable
#synchronized(someArray)
{
// modify array
}
}
If you need to protect more than just one variable you should consider using a semaphore that represents access to that set of data.
// Get the semaphore.
id groupSemaphore = [Group semaphore];
#synchronized(groupSemaphore)
{
// Critical group code.
}
In response to the sStaticData and NSLock answer (comments are limited to 600 chars), don't you need to be very careful about creating the sStaticData and the NSLock objects in a thread safe way (to avoid the very unlikely scenario of multiple locks being created by different threads)?
I think there are two workarounds:
1) You can mandate those objects get created at the start of day in the single root thread.
2) Define a static object that is automatically created at the start of day to use as the lock, e.g. a static NSString can be created inline:
static NSString *sMyLock1 = #"Lock1";
Then I think you can safely use
#synchronized(sMyLock1)
{
// Stuff
}
Otherwise I think you'll always end up in a 'chicken and egg' situation with creating your locks in a thread safe way?
Of course, you are very unlikely to hit any of these problems as most iPhone apps run in a single thread.
I don't know about the [Group semaphore] suggestion earlier, that might also be a solution.
N.B. If you are using synchronisation don't forget to add -fobjc-exceptions to your GCC flags:
Objective-C provides support for
thread synchronization and exception
handling, which are explained in this
article and “Exception Handling.” To
turn on support for these features,
use the -fobjc-exceptions switch of
the GNU Compiler Collection (GCC)
version 3.3 and later.
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/ObjectiveC/Articles/ocThreading.html
Use a copy of the object to modify it. Since you are trying to modify the reference of an array (collection), while someone else might also modify it (multiple access), creating a copy will work for you. Create a copy and then enumerate over that copy.
NSMutableArray *originalArray = #[#"A", #"B", #"C"];
NSMutableArray *arrayToEnumerate = [originalArray copy];
Now modify the arrayToEnumerate. Since it's not referenced to originalArray, but is a copy of the originalArray, it won't cause an issue.
There are other ways if you don't want the overhead of Locking as it has its cost. Instead of using a lock to protect on shared resource (in your case it might be dictionary or array), you can create a queue to serialise the task that is accessing your critical section code.
Queue doesn't take same amount of penalty as locks as it doesn't require trapping into the kernel to acquire mutex.
simply put
dispatch_async(serial_queue, ^{
<#critical code#>
})
In case if you want current execution to wait until task complete, you can use
dispatch_sync(serial_queue Or concurrent, ^{
<#critical code#>
})
Generally if execution doest need not to wait, asynchronous is a preferred way of doing.