synchronized、volatile、ReentrantLock简单了解与对比

文章详细介绍了Java并发编程中的关键概念,包括原子性、可见性和有序性,并讨论了volatile关键字如何保证这两个特性。接着,文章深入分析了synchronized的互斥性和可重入性,以及其在方法和代码块上的应用。最后,提到了ReentrantLock作为更灵活的锁机制,它支持公平锁和非公平锁,并需要手动管理锁的释放。

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

并发编程特性

原子性:对共享资源的一组操作,要么成功要么失败,不会出现部分成功部分失败的情况。

可见性: 当线程获取到琐时,会拷贝一份共享资源到本地内存,释放锁时会将共享资源刷新到主内存中。可见性是指当共享资源发生变化时,其他线程都能够看到这个变化。

有序性:为了提高效率,编译器和处理器会对代码进行指令重排,单线程的情况下,指令重拍不会受到影响,多线程情况下可能会影响代码执行的正确性。有序性是指代码编写顺序和执行顺序是一致的。

volatile

volatile 是JVM提供的最轻量级的同步机制,编译器不会对其进行优化。

特性:

volatile 只保证共享资源的可见性和有序性。

使用volatile修饰共享资源时,如果共享资源变化时,会直接将缓存中的数据写回到主内存中去,数据也是从主内存中读取,从而保证了可见性。

volatile 底层是通过操作系统的内存屏障来实现的,由于使⽤了内存屏障,所以会禁⽌指令重排,从而就保证了有序性。

作用的地方:

volatile 只能用来修饰成员变量。

public class VolatileTest {
    
    private volatile static String staticVolatile;
    
    private volatile String memberVolatile;
}
synchronized

synchronized关键字是java提供的内置锁来保证我们对共享资源的同步,它会自动加锁和释放锁,它的锁是非公平锁, synchronized关键字标记的地方会被编译器进行优化。synchronized会使线程串行执行,可能会造成线程阻塞。

特性

synchronized关键字使线程串行化执行,所以保证了并发安全的3个特性,并且还拥有以下两个特性:

互斥性:同时只有一个线程能够访问synchronized方法或者同步代码块。

可重入性:synchronized是可重入锁,通俗解释可重入锁就是当一个线程获取到了某个对象锁或者类锁之后,这个线程在未释放锁之前,再调用该锁的其他synchronized方法或代码块时,不用再次重新获得锁。

作用的地方

synchronized关键字可用来修饰方法或者代码块。

修饰方法,分为实例方法和静态方法

修饰实例方法,对象锁

public  synchronized void objectMethods(){
   .....
}

修饰静态方法,类锁

public static  synchronized void staticMethods(){
   .....
 }
  1. 修饰代码块

  • obj为对象的引用 对象锁

public  void objectMethods(){
    synchronized (obj){
    }
}
  • Object 为某个类 类锁

public  void classLock(){
    synchronized (Object.class){
    }
}
ReentrantLock

Lock 是 Java 5提供的一个具有锁机制的接口,ReentrantLock 是Lock的一个实现,内部是通过AQS(AbstractQueuedSynchronizer)实现的。ReentrantLock翻译过来是可重入锁,它和synchronized类似,ReentrantLock 需要手动加锁和释放锁, 相对于synchronized它更加灵活,提供了更多的方法。

ReentrantLock 有公平锁和非公平锁两种方式,默认是使用公平锁。

特性

ReentrantLock 是可重入的同步锁,所以它除了具有并发编程的三大特性,还具有可重入性。

作用的地方

ReentrantLock 是一个类,它既可以作为成员变量,也可以作为局部变量使用。做为成员变量和局部变量时,使用的方式有一点点不同,不管使用哪种方式,最后都别忘了要调用unlock() 方法手动释放锁

做为成员变量使用格式:

private Lock globalLock = new ReentrantLock();

public void globalLock(){
    if (globalLock.tryLock()) {
        try {
        } catch (Exception e) {
          
        }finally {
            globalLock.unlock();
        }
    }
}

做为局部变量使用格式:

public void lock(){
     Lock lock = new ReentrantLock();
     lock.lock();
     try {

     }finally {
         lock.unlock();
     }
 }

最后总结一下:

如有不对,请大家指出,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值