同步,何时使用?

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

public static synchronized List sortA(AClass[] aArray) { List aObj = getList(aArray); Collections.sort(aObj, new AComparator()); return aObj; } public static synchronized List getList(AClass[] anArray) { //It converts an array to a list and returns } 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

这可能看起来很明显,但JDK中使用的~99%的StringBuffer只能被一个线程使用,可以用StringBuilder替换(不同步)