在java中线程安全的是_在Java中是=运算符线程安全吗?

否。=操作不是线程安全的。它需要锁定和/或一个适当的链“happens-before”关系,任何涉及到共享字段或数组元素的表达式都是线程安全的。

(使用声明为volatile的字段,“happens-before”关系存在…但仅在读取和写入操作。=操作由读取和写入组成,它们分别是原子的,但序列不是。大多数赋值表达式using =涉及一个或多个读(在右手边)和一个写,这个序列也不是原子的。

对于完整的故事,请阅读JLS 17.4 …或Brian Goetz等人的“Java并发在行动中”的相关章节。

As I know basic operations on primitive types are thread-safe …

其实,这是一个不正确的前提:

>考虑数组的情况

>认为表达式通常由一系列操作组成,并且原子操作的序列不能保证是原子的。

double类型还有一个问题。 JLS(17.7)说:

“For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.”

“Writes and reads of volatile long and double values are always atomic.”

在评论中,你问:

So what type I should use to avoid global synchronization, which stops all threads inside this loop?

在这种情况下(在更新double []时,除了与锁或原语互斥体同步之外,没有其他选择。

如果你有一个int []或long [],你可以用AtomicIntegerArray或AtomicLongArray替换它们,并利用这些类的无锁更新。但是没有AtomicDoubleArray类,甚至没有AtomicDouble类。

(UPDATE – 有人指出,Guava提供了一个AtomicDoubleArray类,所以这将是一个选项,实际上是一个好的。)

避免“全局锁”和大量争用问题的一种方法可能是将数组划分为概念区域,每个区域都有自己的锁。这样,一个线程只需要阻塞另一个线程,如果他们使用数组的相同区域。 (单个写入器/多个读取器锁可以帮助太…如果绝大多数访问是读取。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值