java 同步,何时使用或不使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10581366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:40:11  来源:igfitidea点击:

Synchronization, When to or not to use?

javasynchronized

提问by mu_sa

I have started learning concurrency and threads in Java. I know the basics of synchronized (i.e. what it does). Conceptually I understand that it provides mutually exclusive access to a shared resource with multiple threads in Java. But when faced with an example like the one below I am confused about whether it is a good idea to have it synchronized. I know that critical sections of the code should be synchronized and this keyword should not be overused or it effects the performance.

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

采纳答案by Tudor

Assuming each thread passes a different arraythen no synchronization is needed, because the rest of the variables are local.

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

If instead you fire off a few threads all calling sortAand passing a reference to the same array, you'd be in troublewithout synchronized, because they would interfere with eachother.

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

Beware, that it would seem from the example that the getListmethod returns a new Listfrom an array, such that even if the threads pass the same array, you get different Listobjects. This is misleading. For example, using Arrays.asListcreates a Listbacked by the given array, but the javadoc clearly states that Changes to the returned list "write through" to the array.so be careful about this.

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

回答by Drona

Synchronization is usually needed when you are sharing data between multiple invocations and there is a possibility that the data would be modified resulting in inconsistency. If the data is read-only then you dont need to synchronize.

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

In the code snippet above, there is no data that is being shared. The methods work on the input provided and return the output. If multiple threads invoke one of your method, each invocation will have its own input and output. Hence, there is no chance of in-consistency anywhere. So, your methods in the above snippet need not be synchornized.

在上面的代码片段中,没有正在共享的数据。这些方法处理提供的输入并返回输出。如果多个线程调用您的方法之一,则每次调用都有自己的输入和输出。因此,任何地方都不会出现不一致的情况。因此,您在上述代码段中的方法不需要同步。

Synchronisation, if unnecessarily used, would sure degrade the performance due to the overheads involved and hence should be cautiously used only when required.

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

回答by Peter Lawrey

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

我不会synchronized在单线程代码上使用。即,一个对象不可能被多个线程访问。

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)

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

回答by rishi

There is no rule defined like when to use synchronized and when not, when you are sure that your code will not be accessed by concurrent threads then you can avoid using synchronised.

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

回答by mprabhat

Synchronization as you have correctly figured has an impact on the throughput of your application, and can also lead to starving thread.

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

All get basically should be non blocking as Collections under concurrency package have implemented.

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

As in your example all calling thread will pass there own copy of array, getListdoesn't need to be synchronized so is sortAmethod as all other variables are local.

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

Local variables live on stack and every thread has its own stack so other threads cannot interfere with it.

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

You need synchronization when you change the state of the Object that other threads should see in an consistent state, if your calls don't change the state of the object you don't need synchronization.

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

回答by Greg Kopff

Your static methods don't depend on any shared state, so need not be synchronized.

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