I am running a background thread in my application with dispatch_async and some times my main thread and background thread both access the database same time and this was giving me a database error and I tried to solve it by using sqlite3_threadsafe() which was always returning 2 i.e, i cannot use the same database connection in two threads and I want it to return 1 can anyone help me in this regard
I think you're pursuing the wrong approach. SQLite isn't reliably threadsafe no matter how you compile it — see the FAQ. Even if SQLite is compiled for thread safety, the same database may not be used from multiple threads if any transactions are pending or any statements remain unfinalised.
The recommendations above to use Grand Central Dispatch to funnel all SQLite accesses into a serial dispatch queue are the right way to proceed in my opinion, though I'd be more likely to recommend that you create your own queue rather than use the main queue for the simple reason that you can reliably dispatch_sync when you want to wait on a result.
You can add all of your access statements to, therefore you are always on the main thread when access the sqlite store.
dispatch_async(dispatch_get_main_queue(), ^ {
//code goes here
});
Related
Anyone know if HttpsJwks usage is thread safe?
We got about 60 - 100 calls per second in an application where we are going to use HttpsJwks, but I don't see any locking when it comes to refreshing Jwks.
Also, HttpsJwksVerificationKeyResolver directly call's refresh if it fails to find a key.
Kind regards, Kenneth
It should be, yes. There's no locking but the only shared data is the cache object and it is set with a single assignment. It's used often in multithreaded situations.
I am having a race condition with a NSManagedObjectContext. I was trying out various ways to prevent this using lock on NSManagedObjectContext. Using dispatch_sync seems to be a better approach as suggested by apple. But I am unable to figure out whether an object(being used under a block which is executed using dispatch_sync) can be saved from being accessed by two different threads.
Here is a more clear picture of what I am trying to ask:
[[*Some Singleton class* instance].managedObjectContext executeFetchRequest:request error:&err];
// After fetching results do something in DB
Let's say the above code is passed in a block executed using dispatch_sync like this:
dispatch_sync(someConcurrentQueue, ^{
[[*Some Singleton class* instance].managedObjectContext executeFetchRequest:request error:&err];
// After fetching results do something in DB
});
Can any other thread access [Some Singleton class instance].managedObjectContext before this block is completely executed.
AFAIK it can be accessed. If this is true then, is applying lock on NSManagedObjectContext the only way to prevent this race condition?
As always: It depends
dispatch_sync (and it's even safer cousin dispatch_barrier_sync) cause the queue it's called from to synchronously execute the block. In doing so, they block the thread. This makes one case potentially safe: access from the same thread. What you have to worry about in this scenario is that any reads you do may take place before the block is executed on the queue. Plan accordingly.
But this is ignoring a huge flaw in your code. Managed object contexts should never be shared across threads, or even dispatched off to a different thread from the one they were created on. You can fix your concurrent access problems by simply spawning child contexts.
I have a CONNECT object that make HTTP calls using :
NSURLConnection* connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
In the - (void)connectionDidFinishLoading:(NSURLConnection*)connection method, I write things to a file.
I may have mutiple HTTP calls sent from multiple instances of CONNECT objects, so I suppose there is a risk that those CONNECT objects write into the file at the same time when the connection ends.
Is this correct ? If yes, how may I prevent this ?
If you have only one thread then there won't be any problem as the delegates will be executed on the same thread.
Delegates are executed one after another in single threaded environment. There wont be a case when your DelegateMehtod1 is accessing the file and it has paused due to DelegateMehtod2 and then DelegateMehtod2 access the file. This happens only in multiple threads not in multiple delegates with one thread
If it is multi-threaded environment then you have to synchronize your file accessing code.
Two things:
1) If you are running all the NSURLConnections on a single thread (most likely the main thread), then you won't have any issue with writing to a file as long as you're doing the entire write (ie. open/create, write, close) within the connectionDidFinishLoading method. This is because a single thread can only be doing one thing at a time.
2) On the design side, do you really want multiple connections to be writing to the same file? If you're creating lots of NSURLConnections, then generally you would want to be able to record them, give them unique filenames and process them separately. This then allows you to know how many connections you currently have in flight, cancel them, and so forth.
If you're just writing some short-lived data to a file while you're doing the processing, then perhaps use unique names for the filenames. Basically, I'm finding it hard to think of a good reason to have lots of concurrent downloads writing to the same file on completion - but perhaps you have one!
To improve responsiveness, some synchronous methods that used FMDB to execute SQLite queries on the main thread were rewritten to be asynchronous, and run in the background via -performSelectorInBackground:withObject:. SQLite not being thread-safe, however, each of these methods would ultimately call -[FMDatabase open], decreasing overall performance.
So, I wrote a proxy for the FMDB classes, which overrode -forwardInvocation: to perform -[NSInvocation invokeWithTarget:] on one specific thread, via -performSelector:onThread:withObject:waitUntilDone:. This solved the problem of too many calls to -[FMDatabase open], but -forwardInvocation: itself is rather expensive.
Is there a good way to solve this performance issue without rewriting all of the code that calls FMDB methods?
You've found the problem: don't call -performSelectorInBackground:withObject:! There's no guarantee what it'll do, but it probably won't do the right thing.
If what you want is a single "database thread" for background ops, then there are several options:
Create a new database thread and run loop and use -performSelector:onThread:... instead.
Create an NSOperationQueue with maxConcurrentOperationCount=1 and use NSOperation (NSInvocationOperation, perhaps?), or a serial dispatch queue. This isn't quite right: the operations/blocks are not guaranteed to be executed on the same thread, which might break sqlite (IIRC you can only move a DB handle between threads after freeing all statements)
Use NSOperationQueue, but save a thread-local reference to the database in [[NSThread currentThread] threadDictionary]. This is a bit messy, since you have little control over when the database disappears. It also might violate the NSOperation contract (you're supposed to return the thread to its original state when the operation finishes).
In Apple's Core Data documentation for Concurrency with Core Data, they list the preferred method for thread safety as using a seperate NSManagedObjectContext per thread, with a shared NSPersistentStoreCoordinator.
If I have a number of NSOperations running one after the other on an NSOperationQueue, will there be a large overhead creating the context with each task?
With the NSOperationQueue having a max concurrent operation count of 1, many of my operations will be using the same thread. Can I use the thread dictionary to create one NSManagedObjectContext per thread? If I do so, will I have problems cleaning up my contexts later?
What’s the correct way to use Core Data in this instance?
The correct way to use Core Data in this case is to create a separate NSManagedObjectContext per operation or to have a single context which you lock (via -[NSManagedObjectContext lock] before use and -[NSManagedObjectContext unlock] after use). The locked approach might make sense if the operations are serial and there are no other threads using the context.
Which approach to use is an empirical question that can't be asnwered without data. There are too many variables to have a general rule. Hard numbers from performance testing are the only way to make an informed decision.
Operations started using NSOperationQueue using a maximum concurrent operation count of 1 will not run all operations on the same thread. The operations will be executed one after the other, but a new thread will be created every time.
So creating objects in the thread dictionary will be of little use.
While this question is old, it's actually at the top of Google's search results on 'NSMangedObjectContext threading', so, I'll just drop in a new answer.
The new 'preferred' method is to use the initWithConcurrencyType: and tell the MOC whether it's a main thread MOC or a secondary thread moc. You can then use the new performBlock: and performBlockAndWait: methods on it and the MOC will take care of serializing operations on it's 'native' thread.
The issue then becomes how do you intelligently handle merging the data between the various MOCs your application may spawn, along with a thousand other details that make life 'fun' as a programmer.