使用AtomicInteger是实现线程安全计数器最常用且高效的方法,它基于CAS原子操作,避免锁开销,适用于多数并发场景。

在Java里要弄个线程安全的计数器,其实有几种搞法,最常见的也最省心的,多半就是用
AtomicInteger
直接说解决方案吧,用
AtomicInteger
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadSafeCounter {
private AtomicInteger counter = new AtomicInteger(0); // 初始化为0
/**
* 安全地增加计数器
*/
public void increment() {
counter.incrementAndGet(); // 原子性地增加并获取新值
}
/**
* 安全地减少计数器
*/
public void decrement() {
counter.decrementAndGet(); // 原子性地减少并获取新值
}
/**
* 获取当前计数器的值
* @return 当前计数值
*/
public int getCount() {
return counter.get();
}
public static void main(String[] args) throws InterruptedException {
ThreadSafeCounter tsc = new ThreadSafeCounter();
int numberOfThreads = 10;
int incrementsPerThread = 1000;
Thread[] threads = new Thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < incrementsPerThread; j++) {
tsc.increment();
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join(); // 等待所有线程执行完毕
}
System.out.println("所有线程完成后的最终计数: " + tsc.getCount()); // 预期是 numberOfThreads * incrementsPerThread
}
}当然,你也可以用
synchronized
increment
getCount
synchronized
AtomicInteger
你看,这问题其实挺基础的,但又特别容易被忽略。想象一下,如果你的计数器不是线程安全的,那多个线程同时去‘加1’的时候,就可能出问题了。比如说,线程A读到当前值是5,正准备加1写回6;结果线程B也读到5,它也加1写回6。这下好了,两个线程都加了1,但最终结果却只增加了1,而不是2。这就是典型的‘丢失更新’,数据就这么悄无声息地出错了。这种现象我们管它叫竞态条件(Race Condition),非常麻烦,因为这种错误往往不是每次都发生,而是偶尔出现,调试起来能把人逼疯。尤其在那些对数据一致性要求高的业务场景,比如订单数量、库存统计、访问量统计等等,一旦出现这种问题,轻则数据失真,重则业务逻辑混乱,造成难以估量的损失。所以,理解并解决线程安全问题,是构建健壮并发应用的第一步。
立即学习“Java免费学习笔记(深入)”;
当然了,
AtomicInteger
synchronized
synchronized
synchronized (this)
synchronized (某个对象)
ReentrantLock
java.util.concurrent.locks
synchronized
lock()
unlock()
tryLock()
ReentrantReadWriteLock
finally
ReentrantLock
LongAdder
DoubleAdder
AtomicInteger
AtomicLong
LongAdder
AtomicInteger
选择哪种方案,说到底还是得看你的具体需求和应用场景,没有银弹。
如果你只是需要一个简单的、并发量不是特别高的计数器,或者你的业务逻辑本身就带有锁,那synchronized
synchronized
对于大多数通用场景,特别是需要高效率的原子操作,AtomicInteger
synchronized
如果你的计数器操作非常频繁,而且并发度极高,比如每秒几十万甚至上百万次的增量操作,并且你只关心最终的累加结果,不关心中间的瞬时值,那么LongAdder
而ReentrantLock
Condition
总的来说,我的建议是:优先考虑AtomicInteger
LongAdder
synchronized
ReentrantLock
以上就是如何在Java中实现线程安全的计数器的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号