【问题标题】:Threads and stringbuilder线程和字符串生成器
【发布时间】:2019-11-18 12:07:27
【问题描述】:

我有这段代码应该输出字符串长度 = 10000,但我不断得到不同的输出,我对它究竟是如何发生的感到困惑?是因为例如线程 1 将追加 95 次,然后另一个线程将中断线程 1,例如:线程 2,然后线程 2 在被 t3 等中断之前将追加最多 98 次。?

【问题讨论】:

  • StringBuilder 不是线程安全的。您不能使用并发线程中的一个。用线程安全的 StringBuffer 替换它,你会得到你期望的结果。
  • StringBuilder 不保证线程安全。 stackoverflow.com/a/26860203/2478398。来自文档:“此类设计用于在单个线程正在使用字符串缓冲区的地方用作 StringBuffer 的替代品”
  • 如果您查看StringBuilder 的源代码,您会发现附加字符很有可能被写入目标数组的同一位置,或者计数获胜不正确。这是因为该类不打算同时使用。因此,您的 100 个线程应每个附加 100 个字符(无中断),但有些会被覆盖,因此最终字符串的长度在 100 到 10000 之间。
  • 他们在比赛中,不同步的对象试图聪明地决定每次与它交互时谁获胜,谁失败了。并产生该输出。因为它不是线程安全的。

标签: java multithreading concurrency


【解决方案1】:

StringBuilder 不是线程安全的。您不能使用并发线程中的一个。

将其替换为线程安全的StringBuffer,您将获得预期的结果。

由于它不是线程安全的,因此在不同线程中使用它时,您不能期望得到确定的结果。例如,StringBuilder 的代码可能包含类似

int newIndex = size();
buffer[newIndex] = appendedCharacter;

如果两个线程同时执行这两行,那么两个线程都可能执行第一条指令并为newIndex 获得相同的值,然后都将在相同的索引处插入新字符。这就是所谓的数据竞赛。此类数据竞争是不应在多个线程中使用非线程安全类的主要原因。

【讨论】:

  • 是不是因为当我们使用 StringBuilder 时,我们最终会遇到这种情况? “例如,线程 1 将追加 95 次,然后另一个线程将中断线程 1,例如:线程 2,然后线程 2 在被 t3 等中断之前最多追加 98 次。?”
  • 没有。没有线程被中断。我在答案中解释了原因(数据竞争)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多