当前位置: 首页 > news >正文

Android中的AtomicLong:原理、使用与实战指南

在这里插入图片描述

本文结合生产环境实战案例,带你彻底搞懂AtomicLong在Android多线程开发中的应用。全文包含大量Kotlin代码示例,建议收藏备用。

一、为什么需要AtomicLong?

在Android开发中,当多个线程同时操作同一个Long型变量时,你可能会遇到这样的诡异场景:

var counter = 0L

fun increment() {
    // 这个操作在并发场景下会出错!
    counter++ 
}

这个简单的自增操作,编译后会变成多条JVM指令(ILOAD, LCONST_1, LADD, LSTORE),根本不是原子操作!普通Long变量在多线程环境下存在安全隐患。

二、AtomicLong的核心原理

2.1 CAS机制

AtomicLong底层采用CAS(Compare And Swap)算法:

// 伪代码实现
fun incrementAndGet(): Long {
    while(true) {
        val current = get()
        val next = current + 1
        if (compareAndSet(current, next)) {
            return next
        }
    }
}

这个过程就像超市寄存柜——只有当柜子里的物品和预期一致时,才能放入新物品。通过自旋重试机制保证原子性,但要注意CPU资源消耗。

2.2 内存可见性

通过volatile关键字保证修改的可见性:

// JDK源码片段
private volatile long value;

public final long get() {
    return value;
}

这个设计让所有线程都能立即看到最新值。

三、AtomicLong的基本使用

3.1 初始化方式

// 初始值为0
val atomicCounter = AtomicLong()

// 带初始值
val pageViewCounter = AtomicLong(1000)

3.2 常用方法详解

方法名等价操作说明
get()val = x获取当前值
set(newValue)x = new直接赋值(慎用!)
getAndIncrement()x++先返回旧值再+1(适合计数统计)
incrementAndGet()++x先+1再返回新值
compareAndSet(expect, update)CAS操作核心方法,成功返回true

四、AtomicLong的适用场景

✅ 推荐使用场景

  • 低并发的精确计数器(如页面访问量统计)
  • 需要保证原子性的状态标记(如下载进度百分比)
  • 需要配合其他原子类构建复杂逻辑

⚠️ 不推荐场景

  • 超高并发计数器(考虑LongAdder)
  • 需要保证连续性的操作(如ID生成)

五、生产环境实战案例

5.1 页面访问量统计

class PageVisitTracker {
    private val visitCount = AtomicLong(0)

    // 注意:这个方法要在后台线程调用
    fun trackVisit() {
        visitCount.incrementAndGet()
        if (visitCount.get() % 100 == 0L) {
            uploadToServer() // 每100次上报服务器
        }
    }
    
    fun getVisitCount() = visitCount.get()
}

5.2 下载进度同步

class DownloadManager {
    private val progress = AtomicLong(0)
    
    fun updateProgress(bytes: Long) {
        progress.addAndGet(bytes)
        val current = progress.get()
        if (current % (1024 * 1024) == 0L) { // 每MB更新UI
            runOnUiThread { updateProgressBar(current) }
        }
    }
}

六、性能优化建议

  1. 避免滥用get():频繁调用get()会导致缓存失效
  2. 慎用lazySet:只有在明确不需要立即可见时使用
  3. 注意自旋消耗:高并发下考虑退避策略或改用LongAdder

七、与LongAdder的抉择

当遇到类似需求时:

when {
    writeQPS < 1000 -> AtomicLong()
    writeQPS > 5000 -> LongAdder()
    else -> 根据业务精度要求选择
}

八、常见坑点排查

8.1 原子性误解

错误用法:

if (atomicValue.get() > 100) {
    atomicValue.set(0) // 这两个操作不是原子的!
}

正确姿势:

while (true) {
    val current = atomicValue.get()
    if (current <= 100) break
    if (atomicValue.compareAndSet(current, 0)) break
}

8.2 数值溢出问题

val MAX = Long.MAX_VALUE
val counter = AtomicLong(MAX - 10)

repeat(20) {
    counter.incrementAndGet() // 最后会变成Long.MIN_VALUE
}

九、进阶技巧

9.1 配合Kotlin扩展函数

fun AtomicLong.update(action: (Long) -> Long) {
    while (true) {
        val current = get()
        val newValue = action(current)
        if (compareAndSet(current, newValue)) return
    }
}

// 使用示例
atomicCounter.update { it * 2 }

9.2 性能监控方案

class MonitoredAtomicLong(
    initialValue: Long
) : AtomicLong(initialValue) {
    
    private val casFailureCount = AtomicInteger()
    
    override fun compareAndSet(expect: Long, update: Long): Boolean {
        val success = super.compareAndSet(expect, update)
        if (!success) casFailureCount.incrementAndGet()
        return success
    }
    
    fun printStats() {
        Log.d("AtomicStats", "CAS失败次数:${casFailureCount.get()}")
    }
}

十、总结

AtomicLong像一把精准的手术刀:

  • 优势:精确控制、API丰富、低延迟
  • 局限:高并发下性能衰减明显(当CAS失败率>30%时需警惕)

相关文章:

  • SpringBoot 整合 Vault - 解决敏感配置信息的动态加密与权限管控问题
  • 一些有用的电子书
  • 四十二:VSCODE打开新文件覆盖上一个文件窗口问题
  • 特征工程如何让KNN准确率提升20%?标准化、筛选与编码全解析
  • 动规【力扣】72. 编辑距离
  • 【Python运维】用Python自动化AWS资源管理:利用boto3实现高效管理S3桶和EC2实例
  • MySQL-简介与基本命令
  • LeetCode 热题 100----1.两数之和
  • 题目 3216 ⭐团建⭐【DFS】蓝桥杯2024年第十五届省赛
  • AI 编译器学习笔记之十六 -- TVM
  • 在 MyBatis 中,若数据库字段名与 SQL 保留字冲突解决办法
  • Spring Boot Gradle 项目中使用 @Slf4j 注解
  • 容器与虚拟机:云时代的底层架构博弈
  • 玩转大语言模型——Ubuntu系统环境下使用llama.cpp进行CPU与GPU混合推理deepseek
  • 实时金融信息搜索的新突破:基于大型语言模型的智能代理框架
  • 腾讯云AI代码助手评测:如何智能高效完成Go语言Web项目开发
  • rnmapbox
  • python3.13安装教程【2025】python3.13超详细图文教程(包含安装包)
  • linux离线安装ollama并部署deepseek-r1模型 指南
  • vscode 查看3d
  • 人民日报海外版海外网/优化网站怎么做
  • 做营销策划要用到哪些网站/深圳网络优化seo
  • 网站开发可以用哪些语言/百度百家号登录入口
  • 丹东网站建设/深圳百度地图
  • 专做药材的网站有哪些/微信引流推广怎么做
  • 怎么做创业网站/iis搭建网站