16

我已经开始学习 Java 中的并发和线程。我知道同步的基础知识(即它的作用)。从概念上讲,我理解它提供了对具有 Java 中的多个线程的共享资源的互斥访问。但是当面对像下面这样的例子时,我很困惑让它同步是否是个好主意。我知道代码的关键部分应该同步,并且这个关键字不应该被过度使用,否则会影响性能。

public static synchronized List<AClass> sortA(AClass[] aArray) 
{
    List<AClass> aObj = getList(aArray);

    Collections.sort(aObj, new AComparator());

    return aObj;
}

public static synchronized List<AClass> getList(AClass[] anArray) 
{
    //It converts an array to a list and returns
}
4

6 回答 6

13

假设每个线程传递不同的数组,则不需要同步,因为其余变量是本地的。

相反,如果您触发几个线程,所有线程都调用sortA并传递对同一数组的引用,那么如果没有,您将遇到麻烦synchronized,因为它们会相互干扰。

请注意,从示例中该getList方法似乎从数组返回一个新List的,这样即使线程传递相同的数组,您也会得到不同的List对象。这是误导。例如, usingArrays.asList创建一个List由给定数组支持的,但 javadoc 明确指出,Changes to the returned list "write through" to the array.所以要小心这一点。

于 2012-05-14T10:17:57.460 回答
5

当您在多个调用之间共享数据时通常需要同步,并且可能会修改数据导致不一致。如果数据是只读的,那么您不需要同步。

在上面的代码片段中,没有共享数据。这些方法对提供的输入起作用并返回输出。如果多个线程调用您的方法之一,则每个调用都有自己的输入和输出。因此,任何地方都不存在不一致的可能性。因此,您在上述代码段中的方法不需要同步。

如果不必要地使用同步,由于所涉及的开销,肯定会降低性能,因此只有在需要时才应谨慎使用。

于 2012-05-14T10:23:32.227 回答
2

您的静态方法不依赖于任何共享状态,因此不需要同步。

于 2012-05-14T10:17:15.680 回答
2

没有定义诸如何时使用同步以及何时不使用的规则,当您确定并发线程不会访问您的代码时,您可以避免使用同步。

于 2012-05-14T10:17:57.560 回答
2

您正确计算的同步会影响应用程序的吞吐量,并且还会导致线程不足。

所有 get 基本上都应该是非阻塞的,因为 concurrency 包下的 Collections 已经实现。

在您的示例中,所有调用线程都将传递自己的数组副本,getList不需要同步,sortA方法也是如此,因为所有其他变量都是本地的。

局部变量存在于堆栈中,每个线程都有自己的堆栈,因此其他线程无法干扰它。

当您更改其他线程应在一致状态下看到的对象的状态时,您需要同步,如果您的调用不更改您不需要同步的对象的状态。

于 2012-05-14T10:19:48.320 回答
2

I wouldn't use synchronized on single threaded code. i.e. where there is no chance an object will be accessed by multiple threads.

This may appear obvious but ~99% of StringBuffer used in the JDK can only be used by one thread can be replaced with a StringBuilder (which is not synchronized)

于 2012-05-14T10:35:59.043 回答