有条件地检查 Atomic Integer 线程是否安全?
Conditional checking on Atomic Integer thread safe?
示例代码
@ApplicationScoped
public class AtomicIntegerSample {
private final AtomicInteger successFullSyncCount = new AtomicInteger(0);
private final AtomicLong overallSyncTimeTaken = new AtomicLong(0);
public void incrementSuccessFullSyncCount() {
this.successFullSyncCount.incrementAndGet();
}
public void addOverallSyncTimeTaken(final Long syncTimeTaken) {
overallSyncTimeTaken.addAndGet(syncTimeTaken);
}
/**
* Can be called by multiple threads
* @return
*/
public long getAverageSuccessfulSyncTimeTaken() {
if (successFullSyncCount.get() == 0) {
return 0;
} else {
return overallSyncTimeTaken.get() / successFullSyncCount.get();
}
}
在方法getAverageSuccessfulSyncTimeTaken()
中有条件检查以避免算术异常。
classApplicationScoped,此方法可被多线程并发调用。
方法线程安全吗?。如果我把代码替换成下面这样,线程安全吗?
/**
* Can be called by multiple threads
* @return
*/
public long getAverageSuccessfulSyncTimeTaken() {
return overallSyncTimeTaken.get() / successFullSyncCount.get();
}
然后会抛出算术异常。如何以最佳方式同步此代码?。我的意思是只有 successFullSyncCount.get() == 0
它不会抛出任何异常,但它可能 return 不正确的结果:
- 时间和计数分别递增。它们不会在单个原子操作中同时递增
- 时间和计数是分开读取的,而不是在单个原子操作中同时读取。
因此,您可以很好地在一个线程中读取 100 的时间,然后让另一个线程将计数递增几次,然后读取计数并执行除法。因此,这可能导致每次同步的平均时间低于实际情况。它可能是一个足够好的近似值,也可能不是。
以下是不使用原子对象的版本。
如果您希望时间和计数一起更新,同步块可能更合适。这将防止您的平均方法被多次关闭。诚然,同步块比原生原子实现慢,但我不确定优化是否为时过早。
@ApplicationScoped
public class AtomicIntegerSample {
private int successFullSyncCount = 0;
private long overallSyncTimeTaken = 0;
synchronized public void addSyncTimeTakenAndIncrementSyncCount(final Long syncTimeTaken) {
overallSyncTimeTaken+=syncTimeTaken;
successFullSyncCount++;
}
/**
* Can be called by multiple threads
* @return
*/
public long getAverageSuccessfulSyncTimeTaken() {
if (successFullSyncCount.get() == 0) {
return 0;
} else {
return overallSyncTimeTaken.get() / (float) successFullSyncCount.get();
}
}
示例代码
@ApplicationScoped
public class AtomicIntegerSample {
private final AtomicInteger successFullSyncCount = new AtomicInteger(0);
private final AtomicLong overallSyncTimeTaken = new AtomicLong(0);
public void incrementSuccessFullSyncCount() {
this.successFullSyncCount.incrementAndGet();
}
public void addOverallSyncTimeTaken(final Long syncTimeTaken) {
overallSyncTimeTaken.addAndGet(syncTimeTaken);
}
/**
* Can be called by multiple threads
* @return
*/
public long getAverageSuccessfulSyncTimeTaken() {
if (successFullSyncCount.get() == 0) {
return 0;
} else {
return overallSyncTimeTaken.get() / successFullSyncCount.get();
}
}
在方法getAverageSuccessfulSyncTimeTaken()
中有条件检查以避免算术异常。
classApplicationScoped,此方法可被多线程并发调用。
方法线程安全吗?。如果我把代码替换成下面这样,线程安全吗?
/**
* Can be called by multiple threads
* @return
*/
public long getAverageSuccessfulSyncTimeTaken() {
return overallSyncTimeTaken.get() / successFullSyncCount.get();
}
然后会抛出算术异常。如何以最佳方式同步此代码?。我的意思是只有 successFullSyncCount.get() == 0
它不会抛出任何异常,但它可能 return 不正确的结果:
- 时间和计数分别递增。它们不会在单个原子操作中同时递增
- 时间和计数是分开读取的,而不是在单个原子操作中同时读取。
因此,您可以很好地在一个线程中读取 100 的时间,然后让另一个线程将计数递增几次,然后读取计数并执行除法。因此,这可能导致每次同步的平均时间低于实际情况。它可能是一个足够好的近似值,也可能不是。
以下是不使用原子对象的版本。
如果您希望时间和计数一起更新,同步块可能更合适。这将防止您的平均方法被多次关闭。诚然,同步块比原生原子实现慢,但我不确定优化是否为时过早。
@ApplicationScoped
public class AtomicIntegerSample {
private int successFullSyncCount = 0;
private long overallSyncTimeTaken = 0;
synchronized public void addSyncTimeTakenAndIncrementSyncCount(final Long syncTimeTaken) {
overallSyncTimeTaken+=syncTimeTaken;
successFullSyncCount++;
}
/**
* Can be called by multiple threads
* @return
*/
public long getAverageSuccessfulSyncTimeTaken() {
if (successFullSyncCount.get() == 0) {
return 0;
} else {
return overallSyncTimeTaken.get() / (float) successFullSyncCount.get();
}
}