关于synchronized、volatile、ReentrantLock的区别与对比

 更新时间:2023年04月20日 11:23:55   作者:索码理  
这篇文章主要介绍了关于synchronized、volatile、ReentrantLock的区别与对比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

聊之前先说一下并发编程的3个特性。

并发编程特性

  1. 原子性:对共享资源的一组操作,要么成功要么失败,不会出现部分成功部分失败的情况。
  2. 可见性: 当线程获取到琐时,会拷贝一份共享资源到本地内存,释放锁时会将共享资源刷新到主内存中。可见性是指当共享资源发生变化时,其他线程都能够看到这个变化。
  3. 有序性:为了提高效率,编译器和处理器会对代码进行指令重排,单线程的情况下,指令重拍不会受到影响,多线程情况下可能会影响代码执行的正确性。有序性是指代码编写顺序和执行顺序是一致的。

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(){
   .....
 }

修饰代码块

obj为对象的引用 对象锁

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

Object 为某个类 类锁

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

ReentrantLock

Lock 是 Java 5提供的一个具有锁机制的接口,ReentrantLockLock的一个实现,内部是通过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();
        }
    }
}

上面的tryLock() 方法是尝试获取锁,如果获取成功返回true,否则返回false,也可以换成加了等待时间的 boolean tryLock(long time, TimeUnit unit) 方法,在设定的等待时间内获取锁成功则返回true,否则false。

做为局部变量使用格式:

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

     }finally {
         lock.unlock();
     }
 }

对比

简单对比一下三者之间的区别:

volatilesynchronizedReentrantLock
是否是关键字
是否需要手动加锁/释放锁
是否能保证并发安全
是否是公平锁\有公平锁和非公平锁两种实现
是否会阻塞线程
JVM是否会对其优化
特性可见性、有序性可见性、有序性、原子性可见性、有序性、原子性
使用的地方成员变量方法、代码块成员变量、局部变量

到此这篇关于关于synchronized、volatile、ReentrantLock的区别与对比的文章就介绍到这了,更多相关synchronized、volatile、ReentrantLock的区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 图片叠加效果Java代码实现

    图片叠加效果Java代码实现

    这篇文章主要为大家详细介绍了图片叠加效果Java代码实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • IntelliJ IDEA 2021.3永久最新激活至2099年(亲测有效)

    IntelliJ IDEA 2021.3永久最新激活至2099年(亲测有效)

    最新版idea2021.3已出来,很多网友迫不及待的要升级idea2021最新版,今天小编抽空给大家整理了一篇教程关于idea2021.3最新激活教程,本文以idea2021.2.3为例通过图文并茂的形式给大家分享激活详细过程,感兴趣的朋友参考下吧
    2020-12-12
  • SpringCloud Feign原理剖析

    SpringCloud Feign原理剖析

    feign是用在微服务中,各个微服务间的调用,它是通过声明式的方式来定义接口,而不用实现接口,feign让服务间的调用变得简单,不用各个服务去处理http client相关的逻辑,本文详细介绍SpringCloud Feign原理,需要的朋友可以参考下
    2023-06-06
  • Java初始化List方法代码实例

    Java初始化List方法代码实例

    这篇文章主要介绍了Java初始化List方法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Springboot-Management的项目实践

    Springboot-Management的项目实践

    本文主要介绍了Springboot-Management的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Spring避免循环依赖的策略详解

    Spring避免循环依赖的策略详解

    在Spring框架中,循环依赖是指两个或多个bean相互依赖对方,形成一个闭环,这在应用启动时可能导致BeanCurrentlyInCreationException异常,本文给大家介绍了Spring中如何避免循环依赖,需要的朋友可以参考下
    2024-02-02
  • intellij idea 2021.2 打包并上传运行spring boot项目的详细过程(spring boot 2.5.4)

    intellij idea 2021.2 打包并上传运行spring boot项目的详细过程(spring boot 2

    这篇文章主要介绍了intellij idea 2021.2 打包并上传运行一个spring boot项目(spring boot 2.5.4),本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下
    2021-09-09
  • Java中的弗洛伊德(Floyd)算法

    Java中的弗洛伊德(Floyd)算法

    这篇文章主要介绍了Java中的弗洛伊德(Floyd)算法,Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似,需要的朋友可以参考下
    2024-01-01
  • Java中的JWT使用详解

    Java中的JWT使用详解

    这篇文章主要介绍了Java中的JWT使用详解,JWT是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息,需要的朋友可以参考下
    2023-08-08
  • JDBC连接数据库步骤及基本操作示例详解

    JDBC连接数据库步骤及基本操作示例详解

    这篇文章主要为大家介绍了JDBC连接数据库步骤及基本操作示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11

最新评论