惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Spread Privacy
Spread Privacy
大猫的无限游戏
大猫的无限游戏
F
Fortinet All Blogs
M
MIT News - Artificial intelligence
G
Google Developers Blog
Hacker News: Ask HN
Hacker News: Ask HN
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
V
Visual Studio Blog
WordPress大学
WordPress大学
博客园 - 司徒正美
TaoSecurity Blog
TaoSecurity Blog
Webroot Blog
Webroot Blog
Hugging Face - Blog
Hugging Face - Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
W
WeLiveSecurity
C
CERT Recently Published Vulnerability Notes
Y
Y Combinator Blog
S
Schneier on Security
Recent Announcements
Recent Announcements
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
宝玉的分享
宝玉的分享
T
Troy Hunt's Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 三生石上(FineUI控件)
Microsoft Azure Blog
Microsoft Azure Blog
N
News and Events Feed by Topic
A
About on SuperTechFans
小众软件
小众软件
K
Kaspersky official blog
Help Net Security
Help Net Security
V2EX - 技术
V2EX - 技术
P
Proofpoint News Feed
S
Secure Thoughts
IT之家
IT之家
云风的 BLOG
云风的 BLOG
N
Netflix TechBlog - Medium
The Register - Security
The Register - Security
I
Intezer
NISL@THU
NISL@THU
GbyAI
GbyAI
P
Privacy & Cybersecurity Law Blog
T
Threatpost
C
Check Point Blog
Forbes - Security
Forbes - Security
C
Cisco Blogs
AI
AI
Recorded Future
Recorded Future
F
Full Disclosure

咸糖 - 自律者自由

2025 年终总结:降噪、重构与长期主义 在新加坡和新山吃过最好的食物(持续更新) 写给还在迷茫的你:我的三本大学回忆 2024 年终总结 Neovim: No Crash Incremental Selection 2022 年终总结 使用 neovim 作为 PDE(个性化开发环境) shell 是一个不错的生产力工具 使用二八法则省力地学习 awk 肉身翻墙新加坡安顿指南 使用 Docker Compose 建立你自己的开发环境 关于编写可维护的代码的一些实践与想法 我为什么使用双向链接做笔记? 关于焦虑和拖延症 Golang: 如何处理日渐膨胀的 interface 使用番茄工作法来更好的利用你的时间 Unix 如何杀死一个进程和它的子孙进程? Golang: 让你的零值更有用 使用 Mock 和 Interface 进行 Golang 单测 关于 Golang Slice 的一些细节 总结一些计算机常用的原则 重新学习英语语法 上班族近期小半年入门投资基金组合的学习与实践经历 疫情期间的肉身翻墙新加坡指南 About me 软技能:大厂底层员工打工指南 软技能:我是如何获取知识与信息的? 分布式的令牌桶算法的实现 GC root 在哪里? 什么是 Minor GC/Major GC 漏桶算法的设计与实现 剑指offer 单例模式 TCP 针对面试学习 Actor 如何处理阻塞消息 Akka 源码解析 How to learn scala AES 需要限制 SEED 长度 Java 如何区分==与.equals()方法 2018年年度总结 Java 集合扩容
实现一个AtomicInteger
xiantang · 2020-04-06 · via 咸糖 - 自律者自由

文章目录

【注意】最后更新于 April 6, 2020,文中内容可能已过时,请谨慎使用。

AtomicInteger 顾名思义是一个具有原子化操作的 Integer,与普通的 Integer 的区别是 AtomicInteger 采用一个 CAS 的方式使 Integer 的自增等操作变成原子化操作。

实现的之前需要了解的知识

首先我们先观察 AotmicInteger 的自增操作:

1
2
3
4
5
6
7
8
public final int incrementAndGet() {
         for (;;) {
          int current = get();
          int next = current + 1;
          if (compareAndSet(current, next))
             return next;
          }
 }

他采用了死循环,并且每次循环都获取最新的 value,通过这个值计算出自增后的值,使用 compareAndSet 来交换值,并且判断结果,如果是 true 就返回自增后的值,如果是 false 就进行重试,其实这就是一个典型的 CAS 操作。

并且这个 compareAndSet 操作,其实很简单,就是调用 unsafe 对象的 compareAndSwapInt

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

compareAndSwapInt 就是根据当前对象的所需要 CAS 操作的成员的所在对象的 offset 来进行 CAS 的修改操作。

然后我们来看一下 get () 方法:

1
2
3
4
5
private volatile int value;
public final int get() {
  return value;
}

就是返回 volatile 修饰的值,因为获取这个值是原子化行为,并且 volatile 能保证这个值是最新的。

我的实现

需要注意的是 Unsafe.getUnsafe 是无法直接调用的,因为他会判断是否是 BootStap 的类加载器或者是 Ext 类加载器,如果不是就抛出异常。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class AtomicInteger {
    private static final Unsafe unsafe = getUnsafeInstance();

    private static long offset;

    static {
        try {
            offset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }


    private volatile int value;

    AtomicInteger(int value) {
        this.value = value;
    }

    //通过反射获取对应实例
    private static Unsafe getUnsafeInstance() {
        Field unsafeInstance;
        try {
            unsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
            unsafeInstance.setAccessible(true);
            return (Unsafe) unsafeInstance.get(Unsafe.class);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    int incrementAndGet() {
        int curr;
        int next;
        do {
            curr = get();
            next = curr + 1;
        } while (!unsafe.compareAndSwapInt(this, offset, curr, next));

        return get();
    }

    public int get() {
        return value;
    }
}

文章作者 xiantang

上次更新 2020-04-06

赞赏支持

微信打赏 支付宝打赏