并发编程之ThreadLocal、Volatile、Synchronized、Atomic关键字

本文详细介绍了Java中处理并发编程的四个关键关键字:ThreadLocal、Volatile、Synchronized和Atomic。文章讨论了它们的作用、用法以及内部实现,强调了它们在并发场景下的应用和区别,例如ThreadLocal用于线程内局部变量,Volatile提供可见性但不保证原子性,Atomic提供原子操作,而Synchronized则是线程安全的保证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

工作中用到ThreadLocal、Volatile、Synchronized、Atomic这四个关键字,是时候对它们总结一波了。

共享对象

使用Java编写线程安全的程序关键在于正确的使用共享对象,以及安全的对其进行访问管理。Java的内置锁可以保障线程安全,对于其他的应用来说并发的安全性是使用内置锁保障了线程变量使用的边界。谈到线程的边界问题,随之而来的是Java内存模型另外的一个重要的含义,可见性。Java对可见性提供的原生支持是volatile关键字。

Atomic

作用

对于原子操作类,Java的concurrent并发包中主要为我们提供了这么几个常用的:AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference。
对于原子操作类,最大的特点是在多线程并发操作同一个资源的情况下,使用Lock-Free算法来替代锁,这样开销小、速度快,对于原子操作类是采用原子操作指令实现的,从而可以保证操作的原子性。
通常情况下,在Java里面,++i或者–i不是线程安全的,这里面有三个独立的操作:获得变量当前值,为该值+1/-1,然后写回新的值。在没有额外资源可以利用的情况下,只能使用加锁才能保证读-改-写这三个操作是“原子性”的。
Java 5新增了AtomicInteger类,该类包含方法getAndIncrement()以及getAndDecrement(),这两个方法实现了原子加以及原子减操作,但是比较不同的是这两个操作没有使用任何加锁机制,属于无锁操作。
它会在这步操作都完成情况下才允许其它线程再对它进行操作,而这个实现则是通过Lock-Free+原子操作指令来确定的
AtomicInteger类中:

public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }
public final int get() {  
    return value;  
}  
private volatile int value;
public final boolean compareAndSet(int expect, int update) {  
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
}  

可以看到是一个cas原子操作。
unsafe是java用来在CPU级别的操作CAS指令的类,对于程序员来说,此类是不可用。
由于是cpu级别的指令,其开销比需要操作系统参与的锁的开销小。
对于多个线程进入时,会先比较现在的value 是否与expect相等,如果不相等,则进入下一个循环。如果相等,则会更新成update值。
之后再进入的线程则会死循环。这样就保证了操作的原子性。
这样一个方法中 即包含了原子性,又包含了可见性

而关于Lock-Free算法,则是一种新的策略替代锁来保证资源在并发时的完整性的,Lock-Free的实现有三步

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值