Reputation: 2441
Managed object context initialised with NSMainQueueConcurrencyType and NSPrivateQueueConcurrencyType ties to main queue and private queue which are serial queues where operations are executed in FIFO order.
With below sample code:
NSLog(@"Current thread : %@", [NSThread currentThread]);
[mainMoc performBlock:^{
NSLog(@"main 1 - %@", [NSThread currentThread]);
}];
[mainMoc performBlockAndWait:^{
NSLog(@"main 2 - %@", [NSThread currentThread]);
}];
[mainMoc performBlock:^{
NSLog(@"main 3 - %@", [NSThread currentThread]);
}];
[bgMoc performBlock:^{
NSLog(@"bg 1 - %@", [NSThread currentThread]);
}];
[bgMoc performBlockAndWait:^{
NSLog(@"bg 2 - %@", [NSThread currentThread]);
}];
[bgMoc performBlock:^{
NSLog(@"bg 3 - %@", [NSThread currentThread]);
}];
I was expecting it to print
main 1
, main 2
and main 3
like bg 1
, bg 2
and bg 3
in serial order but instead this was printed:
Current thread : <NSThread: 0x60000006fb80>{number = 1, name = main}
main 2 - <NSThread: 0x60000006fb80>{number = 1, name = main}
bg 1 - <NSThread: 0x600000268900>{number = 3, name = (null)}
bg 2 - <NSThread: 0x60000006fb80>{number = 1, name = main}
bg 3 - <NSThread: 0x600000268900>{number = 3, name = (null)}
main 1 - <NSThread: 0x60000006fb80>{number = 1, name = main}
main 3 - <NSThread: 0x60000006fb80>{number = 1, name = main}
What could be the theory behind it given both main and private queue are serial?
Upvotes: 2
Views: 188
Reputation: 1278
Concurrency is non-deterministic. The only thing you're guaranteed is that "main1" is being executed before "main3", because it is, as you said, a FIFO queue.
It is important to differentiate between performBlock
and performBlockAndWait
.
performBlock
is asynchronous, so it just puts the block into the queue and returns immediately. Those blocks will be executed in order. Thats why "main1" will always be executed before "main3".
performBlockAndWait
is synchronous and thus can't take care of the queue by definition. This means it will execute the block right now and it won't return until it's done.
If it didn't do this, it would block, because the queue isn't empty or it would have to execute all the other tasks in the queue first.
Now the reason for why "bg1" comes before "bg2" is scheduling. I'm almost certain, that if you execute this test multiple times, it might eventually be different. If the main-thread would be faster to reach the synchronous "bg2" it would appear first.
Upvotes: 3