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



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

  • StringBuffer已经存在"永远";。它是线程安全的
  • StringBuilder是";更新的";(最初在Java 1.5中引入)
  • 字符串是不可变的。StringBuffer和StringBuilder都是可变的。使用StringBuffer或StringBuilder比修改原始字符串更有效

根据文档:

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

[StringBuilder]是可变的字符序列。此类提供与StringBuffer兼容的API,但不能保证同步。此类设计用于作为一个插件在字符串缓冲区所在的位置替换StringBuffer由单个线程使用(通常情况下)。哪里可能的话,建议优先使用此类StringBuffer,因为在大多数实现中它会更快。

就我个人而言,我总是优先使用StringBuffer,而不是处理原始字符串。大部分是出于习惯。

是的,StringBuilder可能是";"更快";。或者,在所有的可能性中,它将在总体";性能";。

需要记住的关键点:

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

您可能也对此感兴趣:

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

什么是可变对象

可变对象是指其值可以在初始化后更改的对象。我们可以更改对象的创建对象后的值,如字段和状态。对于例如,Java.util.Date、StringBuilder、StringBuffer等

当我们对现有的可变对象进行更改时,没有新的对象会创建;相反,它将更改现有对象的值。这些对象的类提供了对其进行更改的方法

我读到,如果我们有一个多线程应用程序,那么最好使用StringBuffer。但是,如果我们有一个单线程应用程序,那么最好使用StringBuilder。

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

但是,拥有一个多线程应用程序的全部意义不就是所有线程都可以同时处理同一段代码吗?

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

难道不应该要求如果我们不希望字符串一次被所有线程操作,那么我们应该使用StringBuffer,否则使用StringBuilder也没问题吗?

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

我试图理解的是,对于一个多线程应用程序,为什么需要同步实现

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

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

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

如果我们不希望字符串一次被所有线程操作,那么我们应该使用StringBuffer,否则使用StringBuilder是可以的吗?我试图理解的是,对于一个多线程应用程序,为什么需要进行同步实现(如果需求没有说明这一点)。

是。

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

相关内容