it编程 > App开发 > Android

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

7人参与 2025-03-05 Android

本文结合生产环境实战案例,带你彻底搞懂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的适用场景

✅ 推荐使用场景

不推荐场景

五、生产环境实战案例

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) }
        }
    }
}

六、性能优化建议

七、与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像一把精准的手术刀:

到此这篇关于android中的atomiclong原理、使用与实战指南的文章就介绍到这了,更多相关android atomiclong原理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

Android获取手机安装应用程序的详细信息

03-05

Android 自定义View 加 lifecycle 简单使用详解

03-06

Android使用FFmpeg进行音视频处理指南

03-08

新版Android Studio修改jdk版本的简单步骤

03-10

Android APN数据库查询对比分析(APN案例)

03-01

Android开发中gradle下载缓慢的问题级解决方法

02-27

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论