I was wondering, if I have an object that needs to be synchronized and it's present in several (2-3) places in a block of code, is it better(faster) to add @synchronized to the entire block or just before each object occurrence?
@synchronized (someObj) {
[someObj removeAllObjects];
}
..
@synchronized (someObj) {
[someObj addObject:[NSNumber numberWithInt:203]];
}
VS
@synchronized (someObj) {
[someObj removeAllObjects];
... (potential a large block of code)
[someObj addObject:[NSNumber numberWithInt:203]];
... (potential a large block of code)
}
Any thoughts on this?
What JeremyP said is all true. There are some other things to consider as well. If the first code snippet would work for you, then one could infer that you don't care about any in-between states during (long block of code). (i.e. you're not reading from this array outside an @synchronized block, right?) In that case, you'd be better off batching up the operations that need to be synchronized and doing them all at once. For example:
..
id objectToAdd = [NSNumber numberWithInt: 203];
..
@synchronized (someObj)
{
[someObj removeAllObjects]
[someObj addObject:objectToAdd];
}
Put generally: Concurrency and performance are improved by reducing how many times you take the lock, and how long you hold it when you hold it once you've taken it. In this trivial example, there's nothing to indicate that we couldn't take this lock once, rather than twice, and furthermore, no indication that we couldn't batch the operations like above, explicitly keeping all non-synchronization-needing code outside of the synchronized block.
That said, "Make it work; Make it work right; Make it work fast." -- in that order. I wouldn't waste a lot of time/energy optimizing your locking strategy until you've measured your app and seen that lock contention is a problem.
Any thoughts on this?
Yes.
You can only tell by performance analysis i.e. measuring it.
Obviously releasing and reacquiring the lock is a performance hit, but remember that all of the code in the block is effectively single threaded. So on multi-CPU/core machines, you will lose the advantage of having multiple cores and multiple threads if two threads are both trying to execute the same synchronized block.
Having said the above, my instinct would be to go for multiple small snchronised blocks. In fact in the example you give, I would make the methods -removeAllObjects
and -addObject:
synchronized rather than trying to remember to put them inside synchronized blocks in the calling methods all the time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With