Java codahale metrics Meter mark()方法的线程安全性如何?
我最近开始学习CodaHale/DropWizard度量库。我无法理解Meter类线程是如何安全的(根据文档),尤其是mark()和TickIfEssential()方法: 谢谢Java codahale metrics Meter mark()方法的线程安全性如何?,java,multithreading,dropwizard,metrics,codahale-metrics,Java,Multithreading,Dropwizard,Metrics,Codahale Metrics,我最近开始学习CodaHale/DropWizard度量库。我无法理解Meter类线程是如何安全的(根据文档),尤其是mark()和TickIfEssential()方法: 谢谢 玛丽安在我看来,你是对的。如果调用tickifsemdable(),使得age>TICK\u INTERVAL在另一个调用仍在运行时,则可能会从多个线程同时调用m1Rate.TICK()和其他TICK()方法。因此,它可以归结为tick()及其调用的例程/操作是否安全 让我们仔细分析一下tick(): alpha和i
玛丽安在我看来,你是对的。如果调用
tickifsemdable()
,使得age>TICK\u INTERVAL
在另一个调用仍在运行时,则可能会从多个线程同时调用m1Rate.TICK()
和其他TICK()
方法。因此,它可以归结为tick()
及其调用的例程/操作是否安全
让我们仔细分析一下tick()
:
alpha
和interval
仅在实例初始化时设置,并标记为final那些自只读以来线程安全的count
和instantRate
是本地的,其他线程无论如何都看不到<代码>速率和初始化
被标记为易失性,并且这些写入操作在以下读取中应始终可见
如果我没有错的话,从第一次读取initialized
到最后一次写入initialized
或rate
这对争用是开放的,但有些是无效的,比如当两个线程争用initialized
切换到true
似乎大多数有效的竞争都可以发生在rate+=(alpha*(instantate-rate))代码>特别是删除或混合计算,如:
假设:已初始化
为真
线程1:计算计数
,实例化
,检查初始化
,第一次读取我们称之为上一次速率
的速率
,并因任何原因暂停
线程2:计算计数
,实例化
,检查初始化
,并计算速率+=(alpha*(实例化-速率))代码>
Thread1:继续其操作并计算rate+=(alpha*(instantRate-previous_rate))代码>
如果读取和写入以某种方式进行排序,从而在所有线程上读取rate
,然后在所有线程上写入,则会发生删除,从而有效地删除一个或多个计算
但是这种竞争的概率,意味着两个age>TICK\u INTERVAL
匹配,使得两个线程运行到相同的TICK()
方法,尤其是rate+=(alpha*(instantRate-rate))
可能非常低,这取决于不明显的值
只要对更新/添加和sumThenReset
中的勾选()
方法使用线程安全的数据结构,那么标记()方法似乎是线程安全的
我认为唯一能够回答悬而未决的问题的人是项目作者或对项目的这些部分和计算出的值有深入了解的人,无论这些竞赛是否没有明显的影响或以其他方式减轻影响。这是线程安全的,因为这一行来自tickiffessed()
每newIntervalsStartTick
if (lastTick.compareAndSet(oldTick, newIntervalStartTick))
如果两个线程几乎同时输入tickiffessful()
,会发生什么情况
两个线程从oldTick
读取相同的值,确定至少已过TICK\u间隔
纳秒,并计算newIntervalStartTick
现在两个线程都尝试执行lastTick.compareAndSet(oldTick,newIntervalStartTick)
。正如名称compareAndSet
所示,此方法将当前值lastTick
与oldTick
进行比较,并且仅当该值等于oldTick
时,它才会自动替换为newIntervalStartTick
,并返回true
由于这是一条原子指令(在硬件级别!),因此只有一个线程可以成功。当另一个线程执行此方法时,它将看到newIntervalStartTick
作为lastTick
的当前值。由于此值不再与oldTick
匹配,更新失败,方法返回false,因此此线程不会调用m1Rate.tick()
到m15Rate.tick()
EWMA.update(n)
方法使用一个java.util.concurrent.atomic.longader
来累积事件计数,从而提供类似的线程安全保证。感谢您,到目前为止,我将保持它的打开状态,因此,作者中的某些人可能会注意到这一点。好的,如果由于某种原因,线程将在比较数据集之后挂起/等待if部分,然后会出现另一个勾号。在比较数据集之后,另一个线程也将进入if部件。我的意思是这不太可能,但可能。对吗?你能回答我的评论吗?谢谢。这是可能发生的,但不太可能,因为滴答声每五秒钟发生一次。
public void tick() {
final long count = uncounted.sumThenReset();
final double instantRate = count / interval;
if (initialized) {
rate += (alpha * (instantRate - rate));
} else {
rate = instantRate;
initialized = true;
}
}
public void tick() {
final long count = uncounted.sumThenReset();
final double instantRate = count / interval;
if (initialized) {
rate += (alpha * (instantRate - rate));
} else {
rate = instantRate;
initialized = true;
}
}
if (lastTick.compareAndSet(oldTick, newIntervalStartTick))