android常用的锁 AtomicInteger lock

AtomicInteger是一种乐观锁——非阻塞同步

/**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
}

incrementAndGet()方法在一个无限循环体内,不断尝试将一个比当前值大1的新值赋给自己,如果失败则说明在执行"获取-设置"操作的时已经被其它线程修改过了,于是便再次进入循环下一次操作,直到成功为止。这个便是AtomicInteger原子性的"诀窍"了,继续进源码看它的compareAndSet,可以发现是一种CAS操作

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

在这里插入图片描述

Lock锁的使用方式:

在这里插入图片描述

<think>我们正在讨论Android开发中的选择问题。在Android开发中,我们经常需要处理多线程同步问题,而选择合适的机制至关重要。根据Android系统的特性和开发需求,我们可以考虑以下几种: 1. **synchronized关键字**:这是Java中最基本的,适用于简单的同步场景。在Android中,它同样有效,但需要注意避免过度使用导致性能问题。 2. **ReentrantLock**:这是java.util.concurrent.locks包中的,提供了比synchronized更灵活的操作,比如可中断、可超时、公平等。 3. **ReentrantReadWriteLock**:当读写操作分离时,这种可以提高并发性能,允许多个读操作同时进行,但写操作独占。 4. **StampedLock**:在API 24(Android 7.0)及以上引入,是一种更高效的读写,通过乐观读模式进一步提升性能。 5. **Handler/Looper机制**:在Android中,我们通常使用Handler将任务切换到主线程执行,这本身也是一种同步机制,避免多线程问题。 ### 最佳类型选择建议 1. **简单同步场景**:如果只是简单的代码块同步,使用`synchronized`关键字即可,因为它简洁且不易出错。例如: ```java public class Example { private int count = 0; public synchronized void increment() { count++; } } ``` 2. **需要灵活控制的场景**:如果需要尝试获取、超时或中断,使用`ReentrantLock`。例如: ```java ReentrantLock lock = new ReentrantLock(); if (lock.tryLock(1, TimeUnit.SECONDS)) { try { // 操作共享资源 } finally { lock.unlock(); } } ``` 3. **读写分离场景**:当读操作远多于写操作时,使用`ReentrantReadWriteLock`或`StampedLock`(如果支持API 24+)。例如: ```java ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // 读 lock.readLock().lock(); try { // 读操作 } finally { lock.readLock().unlock(); } // 写 lock.writeLock().lock(); try { // 写操作 } finally { lock.writeLock().unlock(); } ``` 4. **高性能读写场景(API 24+)**:使用`StampedLock`,尤其是乐观读模式: ```java StampedLock lock = new StampedLock(); long stamp = lock.tryOptimisticRead(); // 读操作 if (!lock.validate(stamp)) { stamp = lock.readLock(); try { // 重新读操作 } finally { lock.unlockRead(stamp); } } ``` 5. **UI线程同步**:在Android中,更新UI必须回到主线程,使用`Handler`或`runOnUiThread`: ```java new Handler(Looper.getMainLooper()).post(() -> { // 更新UI }); ``` ### 注意事项 - **避免死**:确保的获取和释放成对出现,尽量在finally块中释放。 - **性能考虑**:的粒度要尽可能小,减少同步区域的大小。 - **Android版本兼容**:如`StampedLock`仅支持API 24及以上,需注意兼容性。 ### 总结 在Android开发中,没有绝对最佳的类型,而是根据具体场景选择: - 简单同步:`synchronized` - 复杂控制:`ReentrantLock` - 读写分离:`ReentrantReadWriteLock`或`StampedLock`(高版本) - UI同步:`Handler`/`Looper` 此外,还可以考虑使用`Atomic`类(如`AtomicInteger`)进行无编程,这在某些场景下性能更高[^4]。 §§相关问题§§ 1. 如何在Android中避免死? 2. 无编程在Android中有哪些应用? 3. 如何选择ReentrantLock和synchronized? 4. 在Android中如何实现线程安全的数据结构?</think>在 Android 开发中,选择最佳类型需要根据具体场景和性能需求进行权衡。以下是各类的对比分析和推荐方案: ### 1. 基础类型对比 | **类型** | **适用场景** | **优点** | **缺点** | **推荐指数** | |----------------------|----------------------------------|----------------------------------|----------------------------------|-------------| | `synchronized` | 简单同步场景 | 语法简单,自动释放 | 功能有限,不支持超时 | ⭐⭐⭐⭐ | | `ReentrantLock` | 需要精细控制的复杂同步 | 支持公平/非公平、可中断、超时 | 需手动释放,代码复杂度高 | ⭐⭐⭐⭐⭐ | | `ReentrantReadWriteLock` | 读多写少场景 | 读写分离提高并发性能 | 写饥饿风险 | ⭐⭐⭐⭐ | | `StampedLock` (API 24+) | 极高并发读写场景 | 乐观读提升性能 | 复杂易错,不支持重入 | ⭐⭐⭐ | ### 2. 最佳实践方案 #### (1) **常规同步场景:`synchronized`** ```java public class Counter { private int count = 0; // 方法级同步 public synchronized void increment() { count++; } // 代码块同步 public void safeOperation() { synchronized(this) { // 临界区操作 } } } ``` > ✅ 适用:简单对象同步、单例模式实现 > ❌ 避免:嵌套(易死) #### (2) **高级控制场景:`ReentrantLock`** ```java ReentrantLock lock = new ReentrantLock(true); // 公平 void performTask() { try { if (lock.tryLock(100, TimeUnit.MILLISECONDS)) { // 超时控制 // 临界区操作 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); // 必须手动释放[^4] } } } ``` > ✅ 适用:需要超时/中断控制的网络请求、复杂事务 > 💡 技巧:结合`Condition`实现精准唤醒 #### (3) **读多写少场景:`ReentrantReadWriteLock`** ```java ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); int getData() { rwLock.readLock().lock(); try { return sharedData; // 并发读 } finally { rwLock.readLock().unlock(); } } void updateData() { rwLock.writeLock().lock(); try { // 独占写 } finally { rwLock.writeLock().unlock(); } } ``` > ✅ 适用:配置数据缓存、日志系统等读密集型操作 #### (4) **高性能场景:`StampedLock` (Android 7.0+)** ```java StampedLock sl = new StampedLock(); // 乐观读 long stamp = sl.tryOptimisticRead(); int value = sharedValue; if (!sl.validate(stamp)) { stamp = sl.readLock(); // 升级为悲观读 try { value = sharedValue; } finally { sl.unlockRead(stamp); } } ``` ### 3. 选择原则 1. **简单优先**:90%场景用`synchronized`足够 2. **避免死**:按固定顺序获取多个 3. **性能敏感**:读多写少用`ReadWriteLock`,极高并发用`StampedLock` 4. **生命周期**:在`onDestroy()`中释放所有资源 ### 4. 特殊场景方案 - **UI线程同步**:使用`Handler`/`runOnUiThread` ```java new Handler(Looper.getMainLooper()).post(() -> { // 主线程安全操作 }); ``` - **原子操作**:优先使用`AtomicInteger`等原子类 - **跨进程通信**:使用`Binder`或`AIDL`的同步机制[^1] > ⚠️ 注意:避免在内执行耗时操作(如网络请求),否则会引发ANR[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值