186人参与 • 2025-03-05 • Android

本文结合生产环境实战案例,带你彻底搞懂atomiclong在android多线程开发中的应用。全文包含大量kotlin代码示例,建议收藏备用。
在android开发中,当多个线程同时操作同一个long型变量时,你可能会遇到这样的诡异场景:
var counter = 0l
fun increment() {
// 这个操作在并发场景下会出错!
counter++
}
这个简单的自增操作,编译后会变成多条jvm指令(iload, lconst_1, ladd, lstore),根本不是原子操作!普通long变量在多线程环境下存在安全隐患。
atomiclong底层采用cas(compare and swap)算法:
// 伪代码实现
fun incrementandget(): long {
while(true) {
val current = get()
val next = current + 1
if (compareandset(current, next)) {
return next
}
}
}
这个过程就像超市寄存柜——只有当柜子里的物品和预期一致时,才能放入新物品。通过自旋重试机制保证原子性,但要注意cpu资源消耗。
通过volatile关键字保证修改的可见性:
// jdk源码片段
private volatile long value;
public final long get() {
return value;
}
这个设计让所有线程都能立即看到最新值。
// 初始值为0 val atomiccounter = atomiclong() // 带初始值 val pageviewcounter = atomiclong(1000)
| 方法名 | 等价操作 | 说明 |
|---|---|---|
| get() | val = x | 获取当前值 |
| set(newvalue) | x = new | 直接赋值(慎用!) |
| getandincrement() | x++ | 先返回旧值再+1(适合计数统计) |
| incrementandget() | ++x | 先+1再返回新值 |
| compareandset(expect, update) | cas操作 | 核心方法,成功返回true |
class pagevisittracker {
private val visitcount = atomiclong(0)
// 注意:这个方法要在后台线程调用
fun trackvisit() {
visitcount.incrementandget()
if (visitcount.get() % 100 == 0l) {
uploadtoserver() // 每100次上报服务器
}
}
fun getvisitcount() = visitcount.get()
}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) }
}
}
}当遇到类似需求时:
when {
writeqps < 1000 -> atomiclong()
writeqps > 5000 -> longadder()
else -> 根据业务精度要求选择
}错误用法:
if (atomicvalue.get() > 100) {
atomicvalue.set(0) // 这两个操作不是原子的!
}
正确姿势:
while (true) {
val current = atomicvalue.get()
if (current <= 100) break
if (atomicvalue.compareandset(current, 0)) break
}val max = long.max_value
val counter = atomiclong(max - 10)
repeat(20) {
counter.incrementandget() // 最后会变成long.min_value
}fun atomiclong.update(action: (long) -> long) {
while (true) {
val current = get()
val newvalue = action(current)
if (compareandset(current, newvalue)) return
}
}
// 使用示例
atomiccounter.update { it * 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原理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论