对于多线程应用程序,为什么需要同步实现(如果要求没有说明)

For a multi-threaded application why is it required to go for a synchronized implementation (if the requirement doesn't state that)

我有一个非常基本的问题。我读过,如果我们有一个多线程应用程序,那么最好使用 StringBuffer。但如果我们有一个单线程应用程序,那么最好使用 StringBuilder。 但是,拥有多线程应用程序的全部意义不就是所有线程都可以同时处理同一段代码吗?要求不应该是如果我们不希望String一次被所有线程操作,那么我们应该去StringBuffer,否则去StringBuilder就可以了吗?我想了解的是对于多线程应用程序,为什么需要同步实现(如果要求没有说明)。

  • StringBuffer 一直存在“永远”。它是线程安全的。
  • StringBuilder 是“较新的”(在 Java 1.5 中首次引入)。
  • String 是不可变的。 StringBuffer 和 StringBuilder 都是可变的。使用 StringBuffer 或 StringBuilder VASTLY 比修改原始字符串更有效。

根据文档:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StringBuilder.html

[StringBuilder] is mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

就个人而言,我总是优先使用 StringBuffer 而不是操作原始字符串。多半是出于习惯。

是的,StringBuilder 可能“更快”。或者,很可能它对整体“性能”的影响很小或没有影响。

要记住的要点:

  • 如果可以改用 StringBuilder 或 StringBuffer,则不要直接操作字符串。
  • StringBuilder 是非同步的(即不是线程安全的)。如果恰好两个线程同时使用StringBuilder,结果将是不确定的。

您可能对此也感兴趣:

https://www.javatpoint.com/mutable-and-immutable-in-java

What are Mutable Objects?

The mutable objects are objects whose value can be changed after initialization. We can change the object's values, such as field and states, after the object is created. For example, Java.util.Date, StringBuilder, StringBuffer, etc.

When we made a change in existing mutable objects, no new object will be created; instead, it will alter the value of the existing object. These object's classes provide methods to make changes in it.

Shouldn't the requirement be that if we don't want the String to be manipulated by all the threads at a time, then we should go for StringBuffer, otherwise it's fine to go for StringBuilder? What I am trying to understand is for a multi-threaded application why is it required to go for a synchronous implementation (if the requirement doesn't state that).

是的。

很少有应用程序 实际上 同时修改字符序列,因此几乎没有理由使用 StringBuffer

I have read that if we have a multi-threaded application then it is better to go with StringBuffer. But if we have a single thread application then it’s better to go with StringBuilder.

这是对一个通常很复杂的问题的非常简单的回答。答案确实应该是,如果多个线程正在 更新 相同的字符串追加器,您应该使用 StringBuffer。如果你有两个线程,并且每个线程都使用自己的本地字符串附加器,那么就不需要为 StringBuffer 同步支付费用,并且可以使用 StringBuilder。您应该知道,无论何时您使用字符串 + 运算符,都会在幕后创建一个 StringBuilder。但是归根结底,我从未见过多个线程共享一个字符串附加程序的情况。

But isn't the whole point of having a multi-threaded application is that simultaneously all the threads can work on the same piece of code?

没有。编写多线程应用程序有很多原因。 Web 服务器使用多个线程,以便可以异步和并行处理 Web 请求,而不必共享任何代码或数据。

Shouldn't the requirement be that if we don't want the String to be manipulated by all the threads at a time, then we should go for StringBuffer, otherwise it's fine to go for StringBuilder?

不完全是。不要认为 StringBuffer 会阻止多个线程操作缓冲区。认为它 保护 缓冲区免受多个线程的不当访问,这会导致竞争条件和其他意外后果。

What I am trying to understand is for a multi-threaded application why is it required to go for a synchronized implementation

没有这样的要求除了当多个线程更新一个对象。如果线程正在处理它们自己的对象并且从不在线程之间共享它们,则不需要同步。如果多个线程正在更新一个对象(例如共享 StringBuffer,则 synchronized 关键字确保更改在线程之间适当地发布,并且关键区域受互斥锁保护,互斥锁确保只有一个线程可以一次输入。

同样重要的是要认识到,如果线程 #1 创建(例如)一个 HashMap,然后线程 #2 想要使用那个 HashMap,即使它没有更新它,然后需要进行某种同步以适当地同步线程 #1 和 #2 之间的 memory

synchronization 强制执行适当的互斥锁,以便关键代码一次只有一个线程在处理它,并确保适当的内存发布,以便线程处理对象的最新版本,而不是可能陈旧的版本在他们的本地内存缓存中。