业务逻辑的同步实现

时间:2011-02-05 07:36:05

标签: java multithreading synchronization

使用现有的同步Java类(Hashtable,StringBuffer,Vector)实现

在实现非同步Java类(HashMap,StringBuilder,ArrayList)时同步块

从Collections.synchronizedXXX()方法创建一个同步的集合对象,然后使用它(当然,我不能像这样同步StringBuilder。!!)

在多线程场景中,上述哪一种是实现同步而没有任何性能下降的最佳方法?

提前致谢。!!!

1 个答案:

答案 0 :(得分:2)

最佳方法取决于您的代码正在尝试做什么以及您需要的原子级别。有时Collections.synchronizedWhatever很好;有时您需要自己进行同步。

就性能而言,您只需确保最小化输入的synchronized块的数量。

之间几乎没有什么区别
(example A)
List l = Collections.synchronizedList(originalList);
l.add(something);

(example B)
synchronized (originalList) {
    originalList.add(something);
}

因为它们都进入一个同步块。但是:

(example C)
List l = Collections.synchronizedList(originalList);
l.add(something);
int index = l.indexOf(something);

将输入两个同步块,而

(example D)
synchronized (originalList) {
    originalList.add(something);
    int index = originalList.indexOf(something);
}

只会输入一个同步块。当然,它在该块中花费的时间更长,因此可能会增加争用,但add和indexOf现在的行为类似于单个原子操作。这可能是您想要的也可能不是:它完全取决于应用程序。

编辑:回答Deepak的问题:

示例C中的'synchronizedList'表示对'l'上的方法的每次调用都将包装在synchronized块中。您可以将C视为:

synchronized (originalList) {
    originalList.add(something);
}
synchronized (originalList) {
    int index = originalList.indexOf(something);
}

这里有一些额外的成本,但除非它在代码的性能关键部分,否则它可能不会成为问题。在您考虑优化代码之前,我建议您更多地考虑确保代码正常运行。很难获得正确的线程安全代码,所以要非常小心你的编写方式。例如,在C中,'l.add(something)'和'l.indexOf(something)'之间存在可能的竞争条件。 D没有相同的竞争条件,因为两个操作都在一个同步块内。

Brian Goetz的书(Java Concurrency in Practice)是学习如何编写线程安全代码的绝佳资源。我强烈推荐它。我确定它在亚马逊上。