Atomic原子类操作
-
AtomicInteger是通过CAS(Compare And Swap)操作来保证原子性的,它具有自己的内置锁,因此不需要使用额外的锁来保证线程安全。在多线程环境中,尽量使用AtomicInteger来代替普通的int类型,可以避免使用传统的同步机制(如synchronized)导致的性能开销。
-
AtomicInteger实现原子操作
private AtomicInteger aLimitNum = new AtomicInteger(1000);
public boolean testLimitMaxNum() {
if (this.aLimitNum == null) {
return true;
}
while (true) {
int oldValue = this.aLimitNum.get();
if (oldValue <= 0) {
return false;
}
int newValue = oldValue - 1;
if (this.aLimitNum.compareAndSet(oldValue, newValue)) {
return true;
}
}
}
首先读取当前的aLimitNum值,然后将其减1,并使用compareAndSet()方法来更新aLimitNum的值。如果更新成功,说明当前线程成功获取到了资源,可以执行后续的操作;如果更新失败,则说明此时已有其他线程更新了aLimitNum的值,当前线程需要重新尝试获取资源,直到成功为止。这样可以保证在多线程环境下,aLimitNum的值始终是正确的,并且每个线程只会执行一次操作。
- AtomicInteger什么情况下需要加锁
AtomicInteger本身已经是线程安全的,不需要额外加锁。但是,如果多个操作需要同时完成,就需要将这些操作组合成一个原子操作,例如:
if (atomicInteger.get() == 0) {
atomicInteger.set(1);
// do something
atomicInteger.set(0);
}
在上述代码中,虽然使用了AtomicInteger,但是在if语句和两个set操作之间可能会发生线程切换,导致原子性失效,因此需要加锁来保证原子性:
synchronized (atomicInteger) {
if (atomicInteger.get() == 0) {
atomicInteger.set(1);
// do something
atomicInteger.set(0);
}
}
这里使用了synchronized关键字来锁住整个操作序列,保证原子性。
- 使用ReentrantLock加锁
private AtomicInteger aLimitNum = new AtomicInteger(1000);
private ReentrantLock limitNumRLock = new ReentrantLock();
public boolean testLimitMaxNum1() {
if (this.aLimitNum == null) {
return true;
}
final ReentrantLock lock = this.limitNumRLock;
lock.lock();
try {
if (this.aLimitNum.get() <= 0) {
return false;
}
this.aLimitNum.decrementAndGet();
} finally {
lock.unlock();
}
return true;
}