我有一個Metrics類,它應該跟蹤我們每秒處理多少個事務以及它們需要多長時間。其結構的相關部分看起來是這樣的:多個變量之間的java線程安全
public class Metrics {
AtomicLong sent = new AtomicLong();
AtomicLong totalElapsedMsgTime = new AtomicLong();
AtomicLong sentLastSecond = new AtomicLong();
AtomicLong avgTimeLastSecond = new AtomicLong();
public void outTick(long elapsedMsgTime){
sent.getAndIncrement();
totalElapsedMsgTime.getAndAdd(elapsedMsgTime);
}
class CalcMetrics extends TimerTask {
@Override
public void run() {
sentLastSecond.set(sent.getAndSet(0));
long tmpElapsed = totalElapsedMsgTime.getAndSet(0);
long tmpSent = sentLastSecond.longValue();
if(tmpSent != 0) {
avgTimeLastSecond.set(tmpElapsed/tmpSent);
} else {
avgTimeLastSecond.set(0);
}
}
}
}
我的問題是,outTick函數將被調用上百次從許多不同的線程中的第二。 AtomicLong已經確保每個變量都是單獨的線程安全,並且它們不會在該函數中彼此交互,所以我不希望一個鎖會讓一個調用outTick阻塞另一個線程調用outTick。如果有幾個不同的線程遞增發送的變量,然後它們都添加到totalElapsedMsgTime變量中,那就很好了。
但是,一旦進入CalcMetrics運行方法(它只發生一次每秒一次),它們就會做交互。我希望確保能夠在不進行outTick調用的情況下重置這兩個變量,或者在接收一個變量和下一個變量之間發生另一個outTick調用。
有沒有辦法做到這一點? (我的解釋是否有意義?)有沒有辦法說A不能與B交錯,但是多個B可以相互交錯?
編輯:
我去,詹姆斯建議ReadWriteLock中。以下是我對任何感興趣的人的結果:
public class Metrics {
AtomicLong numSent = new AtomicLong();
AtomicLong totalElapsedMsgTime = new AtomicLong();
long sentLastSecond = 0;
long avgTimeLastSecond = 0;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock readLock = readWriteLock.readLock();
private final Lock writeLock = readWriteLock.writeLock();
public void outTick(long elapsedMsgTime) {
readLock.lock();
try {
numSent.getAndIncrement();
totalElapsedMsgTime.getAndAdd(elapsedMsgTime);
}
finally
{
readLock.unlock();
}
}
class CalcMetrics extends TimerTask {
@Override
public void run() {
long elapsed;
writeLock.lock();
try {
sentLastSecond = numSent.getAndSet(0);
elapsed = totalElapsedMsgTime.getAndSet(0);
}
finally {
writeLock.unlock();
}
if(sentLastSecond != 0) {
avgTimeLastSecond = (elapsed/sentLastSecond);
} else {
avgTimeLastSecond = 0;
}
}
}
}
謝謝。這看起來像我在找什麼。在我的特定用例中,「讀取」和「寫入」有點用詞不當,因爲我希望在更新它們時使用併發性(並因此使用ReaderLock),並在收集結果時使用專用WriterLock,但至少ReadWriteLock用相同的變量來解決排他性和併發區域兩方面的問題。 (我對這種語言仍然很陌生 - 非常需要學習。) – Lesley
@Lesley,有時它也被稱爲「共享/排他」鎖。 –