【发布时间】:2016-07-02 09:32:20
【问题描述】:
考虑在 Java 中计算成功和失败的统计类。
public class Stat {
long successes=0, failures=0;
public success() {successes += 1;}
public failed() {failures += 1;}
public logStats() { ... read the values and log them ... }
}
应该定期从另一个线程调用logStats() 方法来记录当前的统计计数器。那么这段代码是错误的,因为记录器线程可能看不到最新的值,因为没有任何东西是同步的、易失的或原子的。
因为我使用的是long,甚至volatile 都不够用。甚至这个makes the increment more expensive than without。假设以非常高的频率进行计数,而日志每分钟只运行一次,有没有办法在输入logStats() 时强制将新值分配给所有线程? only logStats() synchronized 会起作用吗?一种半边同步。我知道书上说不要这样做。我只是想了解在这种特定环境下它是否会起作用以及为什么。
另外我应该注意,只有一个线程会进行计数。
编辑请仔细阅读问题所在。我不是在问如何以不同的方式实现这一点。我在问是否以及为什么存在一些半边一致性强制,即写入线程不关心但读取线程主动强制查看最新值。我的直觉是它可能只适用于一个synchronize,但我还不能解释为什么或为什么不。
【问题讨论】:
-
根据this,
volatile在您的情况下是不够的。你必须使用synchronized。 -
您可以使用两个 AtomicLong 计数器。
-
@Daniel 谢谢,你说得对,仅
volatile甚至不适用于long值。相应地改变了问题。 -
@Harald 是否有可能多个线程同时更新
Stats类中的字段,还是只有单个线程频繁更新? -
JVM 规范是怎么说的?
AtomicLong之类的存在是有原因的。
标签: java multithreading volatile