As you may have experienced, access none-thread safe variables is a big headache. For iOS one simple solution is to use keyword #synchronized, which will add NSLock to insure the data can be accessed by unique one thread, the disadvantage is as below:
Lock too many will reduce app performance greatly, especially when invoked by main thread.
Dead lock will occur when logic becomes complex.
Based on the above considerations, we prefer to use serial queue to handle, each thread safe critical operation will append to the end of the queue, it is a great solution, but the problem is that all access interfaces should by designed in asyn style, see the following one.
-(id)objectForKey:(NSString *)key;
The people who invoke this class aren't reluctant to design in this way. Anyone who has experience on this field please share and discuss together.
The final solution is using NSUserDefault to store small data, for large cache data put them in file maintained by ourselves.
Per Apple doc the advantage of NSUserDefault is thread safe and will do synchronize work periodically.
Related
I am designing a singleton class in Objective-C which will be accessed by multiple threads. There are 3-4 NSMutableArrays in my class, outside classes have access with read, add and remove operations which is of course wrapped in this class.
As NSMutableArray is not thread safe, I am using #synchronized() to make my operations thread safe, however it causes too much usage of #synchronized() blocks.
Because for 3-4 array for each I have at least 1 add function, 1 remove function and 5 times I need to read the values. So, for 1 array I am using at least 7 #synchronized() blocks.
For 4 arrays, I need to add 28 #synchronized blocks in my singleton class.
Is there any better way to approach my problem?
or, If I do use too all these #synchronized directives, will it causes problem ?
I know that if I want to make my objects thread safe it will slow down my code, but besides that is there any drawback?
Typically it is not sufficient to just synchronize the primitive calls (CRUD) to gain thread safety. This fine granular level is just the basic, but you'll also have to think on a more global level and "atomize" larger amounts of code. How to do this is highly dependend on your actual implementation. Multithreading is evil(tm) and demands a comprehensive view, so there is no general answer for this.
Synchronized blocks will typically slow down your application, at least if they are called too frequently. Sometimes it's better to group multiple calls in one synchronized block, to avoid the locking overhead. Or you could use spin locks, if the calls are very short, to prevent unnecessary task suspensions (see here for an old question/answer).
For more details you can just consult the Apple documentation.
I'm working on some code that I can't contact the original developer.
He passes a class a reference to another class's serial dispatch queue and I'm not seeing any purpose to him not just creating another dispatch queue (each class is a singleton).
It's not creating issues but I'd like to understand it further, so any insight into the positive implications is appreciated, thank you.
Edit: I suggest reading all the answers here, they explain a lot.
It's actually not a good idea to share queues in this fashion (and no, not because they are expensive - they're not, quite the converse). The rationale is that it's not clear to anyone but a queue's creator just what the semantics of the queue are. Is it serial? Concurrent? High priority? Low priority? All are possible, and once you start passing internal queues around which were actually created for the benefit of a specific class, the external caller can schedule work on it which causes a mutual deadlock or otherwise behaves in an unexpected fashion with the other items on that queue because caller A knew to expect concurrent behavior and caller B was thinking it was a serial queue, without any of the "gotchas" that concurrent execution implies.
Queues should therefore, wherever possible, be hidden implementation details of a class. The class can export methods for scheduling work against its internal queue as necessary, but the methods should be the only accessors since they are the only ones who know for sure how to best access and schedule work on that specific type of queue!
If it's a serial queue, then they may be intending to serialize access to some resource shared between all objects that share it.
Dispatch queues are somewhat expensive to create, and tie up system resources. If you can share one, the system runs more efficiently. For that matter, if your app does work in the background, using a shared queue allows you to manage a single pool of tasks to be completed. So yes, there are good reasons for using a shared dispatch queue.
My understanding of threads with respect to an NSManagedObjectContext is that it can only execute core data fetch requests, deletes, etc., on the thread from which it was created. Is there any way to check to see what thread an NSManagedObjectContext was created on, or if at a particular point of execution the current thread is that of a particular NSManagedObjectContext?
Thanks!
My understanding of threads with respect to an NSManagedObjectContext is that it can only execute core data fetch requests, deletes, etc., on the thread from which it was created.
That's not really accurate. It would be better to say that contexts cannot be used concurrently by more than one thread or queue. A common approach to dealing with this is to create different contexts for each thread/queue. It's also possible to use the performBlock and performBlockAndWait methods to use contexts on multiple threads while keeping context access effectively single-threaded.
As a result, contexts don't have any notion of belonging to a thread or queue, nor do threads have any reference to contexts that were created on them.
If you follow the approach of one context per thread or queue, you need to keep track of where code will run and use the appropriate context. For example when using GCD, create a context for a specific dispatch queue, and only use it when you've used something like dispatch_async to run on that queue.
If you really want to link a context with a queue, you could use your own data structure to look up contexts from whatever concurrency scheme you're using-- by the current NSOperationQueue, or dispatch queue, or NSThread, or whatever. This is rarely needed, but it's a possibility if you can't find better techniques.
As far as I know you can't. At least not too easily. Why? Use -performBlock: - it will perform all requests on the correct thread.
Sorry Tom Harrington, but that's actually not at all correct. Although you can technically do this, the results will be random and usually (in my experience) result in race conditions that become extremely difficult to debug.
The DOCs explicitly indicate that you should use a context PER thread. In fact even some of the best frameworks around (i.e. MagicalRecord) behave in this way. NSManagedObject's and their contexts are NOT thread safe, however objectIDs are.
To check for changes, you could either persist your changes up to the parent context's or you can listen to the notifications provided. Using the second method, you'll then need read the objectIDs of the item(s) you want to access, then request them again from your local context.
Read the following Apple Documentation to better understand how this works.
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html
After further research I have found a document last updated over the past few weeks and although you are correct in regards to the performBlock methods it does still state that you should not pass contexts between threads. Perhaps I misread the question and responded a little quickly. I've recently been working on a large CoreData based application and I know we have had a lot of issues related to contexts and threads, so I responded a little quick. ;)
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/NSManagedObjectContext.html
I am confused on where to use which multithreading tool in iOS for hitting services and changing UI based on service data,
firstly I got accustomed to using NSURLConnection and its delegates, used didreceiveresponse, didreceivedata etc delegates to achieve the task
secondly I learned and used GCD to hit services and update the UI from within the block code
Now I am learning to use performSelectorInBackground() to do work in background thread
Clearly confused on which tool to use where?
NSURLConnection with delegate calls is "old school" way of receiving data from remote server. Also it's not really comfortable to use with few NSURLConnection instances in a single class (UIViewController or what not). Now it's better to use sendAsynchronousRequest.. method with completion handler. You can also define on which operation queue (main for UI, or other, background one) the completion handler will be run.
GCD is good for different tasks, not only fetching remote resources with initWithContentsOfURL: methods. You can also control what type of queues will receive your blocks (concurrent, serial ,etc.)
performSelectorInBackground: is also "old school" way of performing a method in background thread. If you weren't using ARC, you'd need to setup separate autorelease pool to avoid memory leaks. It also has a limitation of not allowing to accept arbitrary number of parameters to given selector. In this case it's recommended to use dispatch_async.
There are also NSOperationQueue with NSOperation and its subclasses (NSInvocationOperation & NSBlockOperation), where you can run tasks in the background as well as get notifications on main thread about finished tasks. IMHO They are more flexible than GCD in a way that you can create your own subclasses of operations as well as define dependencies between them.
The most important thing is, that you never change UI anyway in another thread except the main thread.
I think, that all points you mentioned use the same technique in the background: GDC. But I'm not sure of that.
Anyway it doesn't matter which tool you should use in terms of threading.
It's rather a question of your purpose. If you wan't to fetch an small image or just few data you can use contentsOfURLin a performSelectorInBackground() or a GDC dispatch block.
If it's about more data and more information like progress or error handling you should stick with *NSURLConnection`.
I suggest using GCD in all cases. Other techniques are still around but mainly for backward compatibility.
GCD is better for 3 reasons (at least):
It's extremely easy to use and the code remains very readable because of the use of blocks
It is lower level than things like NSOperation so it is much faster when you need high performance multi threading
It's lightweight and non-intrusive so your code doesn't have to change substantially when you want to add thread management in the middle of a method.
I have been working on a JSON parser for a little while https://github.com/nathanday/ndjson that parsers a stream of bytes instead of a complete document and convert directly into CoreData entities or custom objects instead of the usual property list objects. I am close to a version 1.0 but I have gotten to a point where to support NSURLConnection connection properly and to make parsing zipped JSON byte streams easier I have to change the way my parse internally works so that it can be called repeated (with the NSData objects the NSURLConnectionDelegate didReceiveData: method for example).
I have two choice that I can think of, the simplest is use a thread to wait on the next piece of data available, or alternately I can rewrite the parsing part of my code so that it can be repeatedly be called, picking up from where it last was by creating my own stake for the variables that need to be maintained between calls.
Using threads is simplest as it doesn't require very little rewriting if any, but as this is supposed to be a library for general use I am concerned about creating more threads than needed on a resources constrained device like the iPhone. Of cause the other options will make the code more complicated and having to maintain my own stack will not be resource free.
Does anybody have any good advice or maybe another possible options. Is creating threads expensive. Maybe someone can think of a creative way using block, or is it possible to call the NSRunLoop object to execute the next event (NSURLConnectionDelegate methods).
Under iOS and OS X, Apple provides a great way to do threads without headache: Grand Central Dispatch. Threads aren't expensive, and the system take care of creating the threads for you.
You can use serial queues to process your data and then sync it on the main thread using blocks:
// create the queue that will process your data:
dispatch_queue_t dataProcessQueue = dispatch_queue_create("data process queue", NULL); // the name is there for debugging purposes
//dispatch to the newly created queue, and do not wait for it to complete
dispatch_async(dataProcessQueue, ^{
//your asynchronous job
dispatch_async(dispatch_get_main_queue(), ^{
// the work that has to be done on your main thread using data from above
});
});
// don't forget to release the queue
dispatch_release(dataProcessQueue);
If you need to do concurrent work, you should use concurrent queues.
Apple's documentation is here