我想知道,如果我有一个需要同步的对象并且它存在于代码块中的几个(2-3)位置,那么将@synchronized添加到整个块或者只是更好(更快)在每个对象发生之前?
@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)
}
对此有何想法?
答案 0 :(得分:13)
JeremyP所说的都是真的。还有一些其他事情需要考虑。如果第一个代码片段适合您,那么可以推断您在(长代码块)期间不关心任何中间状态。 (即你不是从@synchronized块之外的读取这个数组,对吗?)在这种情况下,你最好还是批量完成需要同步的操作并在一旦。例如:
..
id objectToAdd = [NSNumber numberWithInt: 203];
..
@synchronized (someObj)
{
[someObj removeAllObjects]
[someObj addObject:objectToAdd];
}
一般来说:并发性和性能通过减少锁定次数以及持有它持有多长时间来改善。在这个简单的例子中,没有任何迹象表明我们不能一次,而不是两次,而且,没有迹象表明我们不能像上面那样批处理操作,明确地将所有不需要同步的代码保持在同步块。
那说,“让它发挥作用;让它正常工作;让它快速工作。” - 以该顺序。在您测量应用程序并发现锁定争用存在问题之前,我不会浪费大量时间/精力来优化您的锁定策略。
答案 1 :(得分:6)
对此有何想法?
是
您只能通过性能分析来判断,即测量它。
显然,释放和重新获取锁是一个性能损失,但请记住,块中的所有代码都是有效的单线程。因此,在多CPU /核心机器上,如果两个线程都试图执行相同的同步块,您将失去拥有多个内核和多个线程的优势。
说完上面的话后,我的本能就是选择多个小型的同步块。事实上,在您给出的示例中,我将使方法-removeAllObjects
和-addObject:
同步,而不是试图记住将它们一直放在调用方法中的同步块中。