net.openhft.chronicle.bytes.DistributedUniqueTimeProvider是否线程安全?
DistributedUniqueTimeProvider.currentTimeNanos 是否线程安全?
问题背景
查看DistributedUniqueTimeProvider.currentTimeNanos的实现:
long time = provider.currentTimeNanos(); long time0 = bytes.readVolatileLong(LAST_TIME); long timeN = timestampFor(time) + hostId; if (timeN > time0 && bytes.compareAndSwapLong(LAST_TIME, time0, timeN)) return timeN; return currentTimeNanosLoop();
该方法默认依赖SystemTimeProvider,其currentTimeNanos实现如下:
long nowNS = System.nanoTime(); long nowMS = currentTimeMillis() * NANOS_PER_MILLI; long estimate = nowNS + delta; if (estimate < nowMS) { delta = nowMS - nowNS; return nowMS; } else if (estimate > nowMS + NANOS_PER_MILLI) { nowMS += NANOS_PER_MILLI; delta = nowMS - nowNS; return nowMS; } return estimate;
其中delta是非volatile、非原子类型的成员变量:
private long delta = 0;
疑问:DistributedUniqueTimeProvider.currentTimeNanos到底是否线程安全?若是,原因是什么?
回答
DistributedUniqueTimeProvider.currentTimeNanos是线程安全的,核心原因分为两点:
1. 核心逻辑的线程安全保障
DistributedUniqueTimeProvider的核心逻辑依赖volatile读取和CAS原子操作:
bytes.readVolatileLong(LAST_TIME)保证所有线程能读取到LAST_TIME的最新值,避免脏读;bytes.compareAndSwapLong(LAST_TIME, time0, timeN)是原子性操作,确保同一时刻只有一个线程能成功更新LAST_TIME,失败的线程会进入currentTimeNanosLoop()循环重试,直到生成一个比当前LAST_TIME更大的唯一时间戳。
这部分逻辑从根本上避免了竞态条件,保证时间戳的唯一性。
2. SystemTimeProvider中delta的非线程安全不影响整体正确性
虽然delta是非volatile、非原子的,多线程下可能出现可见性问题或并发修改,但这只会影响时间戳的精度,不会破坏DistributedUniqueTimeProvider的核心目标——生成唯一时间戳:
delta的作用是校准System.nanoTime()和System.currentTimeMillis()的偏差,即便多线程下delta的值被脏读或修改错误,最终返回的时间戳要么是毫秒级的nowMS(本身单调递增),要么是基于nowNS+delta的估算值;- 就算估算值出现偏差,后续
timestampFor(time)会将时间戳对齐到指定粒度,加上唯一的hostId后,最终通过CAS操作保证timeN一定大于LAST_TIME,确保时间戳全局唯一。
简言之,delta的非线程安全最多让时间戳精度偶尔出现小误差,但绝不会导致重复的时间戳,因此DistributedUniqueTimeProvider.currentTimeNanos整体是线程安全的。
内容的提问来源于stack exchange,提问作者HeavyLifter
相关产品推荐
相关产品推荐

