同步,何时使用?

时间:2012-05-14 10:14:10

标签: java synchronized

我已经开始在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
}

6 个答案:

答案 0 :(得分:12)

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

相反,如果您启动了几个线程全部调用sortA并将引用传递给同一个数组,您将遇到麻烦没有synchronized,因为它们会互相干扰。

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:2)

没有定义规则,比如何时使用synchronized,当不确定时,如果您确定并发线程不会访问您的代码,那么您可以避免使用synchronized。

答案 4 :(得分:2)

正确计算的同步会对应用程序的吞吐量产生影响,并且还会导致饥饿线程。

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

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

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

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

答案 5 :(得分:2)

我不会在单线程代码上使用synchronized。即多个线程无法访问对象的情况。

这可能看似显而易见但是JDK中使用的~99%的StringBuffer只能被一个线程使用,可以用StringBuilder替换(不同步)