为什么Java有了synchronized之后还造了Lock锁这个轮子?

DataWorks PyODPS第三方包全攻略:从打包到加载的完整流程 本文详细介绍了在DataWorks的PyODPS节点中使用第三方Python包的完整流程,包括环境限制、打包工具pyodps-pack的使用、资源上传与加载实战,以及特殊场景处理技巧。通过本文,开发者可以掌握在MaxCompute受限环境中灵活使用自定义依赖的方法,提升数据处理效率。 阅读详情

众所周知,synchronized和Lock锁是java并发变成中两大利器,可以用来解决线程安全的问题。但是为什么Java有了synchronized之后还是提供了Lock接口这个api,难道仅仅只是重复造了轮子这么简单么?本文就来探讨一下这个问题。

谈到这个问题,其实很多同学第一反应都会说,Lock锁的性能比synchronized好,synchronized属于重量级的锁。但是在JDK 1.6版本之后,JDK对synchronized进行了一系列性能的优化,synchronized的性能其实有了大大的提升(如果不清楚的同学可以看一下 synchronized真的很重么? 这篇文章,文章内详细的说明JDK对synchronized做了哪些优化),那么既然性能不是问题,那么主要的问题是什么呢?

synchronized抢占锁的特性

我们先来看一下synchronized抢占锁的特性。synchronized在抢占锁的时候,如果抢占不到,线程直接就进入阻塞状态了,而线程进入阻塞状态,其实什么也干不了,也释放不了线程已经占有的资源,并且也无法主动或者被动打断阻塞获取锁的操作,只有等别的线程释放锁之后才会被唤醒来重新获取锁。

synchronized阻塞获取锁产生的问题

那synchronized这种获取锁阻塞的特性,有什么问题么?其实有一种很重要的问题,那就是会产生死锁的问题。

那什么是死锁?死锁是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待的现象。

举个例子来说,线程1先对加A加锁,线程2对B加锁。代码运行到某一时刻,线程1需要对B加锁,但是此时B的锁已经被线程2占有,于是线程1就会阻塞,与此同时线程2同时也需要对A加锁,发现A已经被线程1持有,也会进入阻塞,于是线程1和线程2都在等对方释放资源,就产生了死锁的问题,并且由于synchronized阻塞的特性,线程无法主动或者被动停止阻塞,势必会导致这个死锁永远无法通过主动或者人为干预(其它线程干预)来解决。

那么有什么好的办法来解决阻塞导致死锁的问题呢?

我们分析一下死锁产生的问题主要是线程都在相互等待其它线程释放资源导致的,基于这个问题我们思考一下,如果一个线程获取不到锁,然后就停止获取锁,不阻塞,或者是阻塞一会就不再阻塞,又或是阻塞过程中被其他线程打断,那样这是不是就不是产生死锁的问题了。

就拿上面的例子来说,假设线程1获取B的阻塞锁超过一定时间,主动放弃获取B的锁,那么线程1代码就可以继续往下执行,当执行完之后,线程1释放了A锁,此时线程2就能获取到A的锁,那么线程2就可以继续执行了,这样是不是死锁的问题就完美解决了。

其实Lock锁就提供了上述提到的几种解决方案的api,接下来我们就来看看Lock锁提供的api。

Lock锁

void lockInterruptibly() throws InterruptedException;

阻塞可以被打断的加锁方法,这是一个被动放弃获取锁的方法。就是说其它线程主动当调用阻塞线程的interrupt方法之后,该阻塞线程就会放弃继续获取锁,然后抛出InterruptedException 异常,所以对于使用方来说,只要捕获这个异常,就能保证线程的代码继续执行了。

boolean tryLock();

这个方法是尝试加锁,加锁失败后就放弃加锁,不会阻塞,直接返回false。

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

这个方法相比上面的就是尝试加锁失败后在阻塞的一定时间之后,如果还没有获取到锁,那么就放弃获取锁。

Lock接口的实现有很多,但基本上都是基于Java的AQS的实现来完成的。AQS其实主要是维护了一个锁的状态字段state和一个双向链表。当线程获取锁失败之后,就会加入到双向链表中,然后阻塞或者不阻塞,这得看具体的方法实现。

Lock接口的一个实现ReentrantLock就是基于AQS实现来讲的,这里就不继续展开讲解ReentrantLock的实现原理,如果有感兴趣的同学,可以看一下 一文带你看懂Java中的Lock锁底层AQS到底是如何实现的 这篇文章,文章是基于ReentrantLock来讲解AQS的加锁和释放锁的原理。

总结

好了,到这里其实大家应该知道了,为什么需要Lock锁,因为synchronized获取不到锁的时候会阻塞,并且阻塞不可被打断的特性会导致可能会产生死锁的问题,为了解决这个问题,Java就提供了Lock锁的实现,从主动放弃获取锁或者被动放弃获取锁的方式,解决一直阻塞可能产生的死锁问题。

避坑指南:C# OPC UA 客户端开发中证书、超时与连接的那些‘坑’ 本文深入剖析C# OPC UA客户端开发中的常见陷阱,包括证书管理、会话超时与连接恢复等核心问题。针对UA-.NETStandard库在生产环境中的典型故障场景,提供实战解决方案与优化配置模板,帮助开发者构建稳定可靠的工业物联网通信系统。 阅读详情

相关推荐

【重启后nvidia-smi 命令出现错误】

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

qq_44769377的博客 5216

Java锁机制,synchronized和lock详解。

Java锁机制详解

记录开发日常笔记 7448

VLP16:使用pointcloud_to_laserscan将三维点云转化为二维LaserScan

velodyne16线激光雷达 VLP16:使用pointcloud_to_laserscan将三维点云转化为二维LaserScan

NEUer_ljx的博客 4623

10-锁(synchronized和Lock)

锁(synchronized和lock)

titanium的博客 3968

别再为PCB和散热器文件发愁了!手把手教你用ADS导出DWG文件给工厂(附单位转换避坑指南)

本文详细解析了从ADS设计到PCB/散热器加工的DWG文件导出全流程,重点介绍了单位转换、分层导出策略及散热器文件处理等关键步骤,帮助射频工程师避免加工误差和返工。特别提供了mil与mm单位转换的精确处理方法,确保设计文件与工厂加工需求无缝对接。

weixin_30814329的博客 617

ARM架构福音:在飞腾FT-2000/4开发板上,用Clonezilla Live 2.6.6-11给麒麟V10系统做个‘快照’

本文详细介绍了在飞腾FT-2000/4开发板上使用Clonezilla Live 2.6.6-11为麒麟V10系统创建备份的完整方案。针对ARM架构的特殊挑战,提供了从工具准备到备份执行的全流程指南,包括镜像获取、U盘制作、备份配置及性能优化技巧,帮助用户实现高效可靠的系统备份。

weixin_30889885的博客 607

Java 中的 synchronized 与 Lock:深度对比、使用场景及高级用法

本文将从底层原理、语法结构、使用场景、优缺点、最佳实践等多个维度对 synchronized 和 Lock 进行全面深入的解析,并通过大量代码示例帮助你更好地理解它们之间的区别与联系。

小小菜鸟的博客 1866

CANoe开发入门到精通读书笔记(2)——CAPL编程

CAPL函数的语法跟C语言很类似,但也包含一些C语言所不具备的功能大部分CAPL支持的数据类型都可以直接声明为函数参数, 例如,整型、浮点型、枚举、结构、定时器以及它们的引用。但有一些类型不能被直接声明,而需要加上*号(注意该符号并不是C语言中 指针的意思)。例 如 : signal * s 、 envvarInt * ev 、 sysvarFloat * sv 、 diagRequest * dr、diagResponse * dr、int matrix[][],以及。

weixin_66275497的博客 6462

JAVA之Synchronized和Lock

ReentrantLock

群鸟飞扬 516

构建栅格地图matlab代码

1 使用MATLAB实现地图栅格化 效果图如下所示 图1 ...

qq_59747472的博客 4519

基于网关实现不同网段S7-1200 CPU的通信方法

在A网段的计算机上ping B网段的计算机:在A网段的计算机上使用ping命令,向B网段的计算机发送数据包。在B网段的计算机上ping A网段的计算机:同样地,在B网段的计算机上使用ping命令,向A网段的计算机发送数据包。数据包也会经过路由器进行转发,最终到达A网段的计算机。配置路由器:在路由器上配置两个网段的IP地址和子网掩码,并设置路由表,使得路由器可以将A网段和B网段之间的数据进行转发。确定两个网络之间的路由器:假设需要将A网段和B网段进行通信,需要在A、B两个网段之间设置一台路由器。

电工 2402

java synchronized和Lock

synchronized 的使用 一:synchronized 和Lock 的区别 1、synchronized是java内置关键字,Lock是ava.util.concurrent.locks包下常用的类 2、synchronized会自动释放锁,(线程执行完同步代码会释放锁,出现异常会自动释放锁)Lock是java.util.concurrent.locks包下常用的类,Lock需在fina...

小十木的博客 908

【ROS2实体机械臂驱动】封装珞石ROS2驱动库ros2_rokae_driver_lib

这一篇文章将封装为,和之前一篇文章《ROS2 编译、打包、封装三方库(Knet为例)_ros插件编译成静态库-优快云博客》写的封装,区别在于优化了cmake dependencies和include等属性和宏定义,同时对于多库内部依赖的情况做了特定处理,更加方便外部调用。其中珞石的编译参考博主之前的文章rokae xCoreSDK C++测试使用,这里不再做赘述。通过这篇文章对于如何打包机械臂厂家提供的三方库做了进一步说明,方便用于不同机械臂厂家的三方库封装调用。!!

机器人梦想家 Bing Lee 1400

【高并发】面试官:Java中提供了synchronized,为什么还要提供Lock呢?

我又答对了!!

冰河的专栏 5328

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java:既然有了synchronized,为什么还要提供Lock?

在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是不是重复造轮子,多此一举呢?

华为云官方博客 1234

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Synchronized和Lock的区别,面试问Java提供了synchronized,为什么还要提供Lock呢?

Synchronized和Lock的区别: Synchronized编码更简单,锁机制由JVM维护,在竞争不激烈的情况下性能更好。Lock功能更强大更灵活,竞争激烈时性能较好。 1.性能不一样:资源竞争激励的情况下,lock性能会比synchronize好,竞争不激励的情况下,synchronize比lock性能好,synchronize会根据锁的竞争情况,从偏向锁–>轻量级锁–>重量级锁升级,而且编程更简单。 2.锁机制不一样:synchronize是在JVM层面实现的,系统会监控

胡麻油 1070

Java有了synchronized,为什么还要提供Lock

在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?

华为云官方博客 1184

有了synchronized为何还要提供Lock?重复造轮子?

写在前面 在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是不是重复造轮子,多此一举呢?今天,我们就一起来探讨下这个问题。 再造轮子? 既然JVM中提供了synchronized关键字来保证只有一个线程能够访问同步代码块,为何还要提供Lock接口呢?这是在重复造轮子吗?Java的设计者们为何要这样做呢?让我们一起带着疑问往下看。 为何提供Lock接口? 很

互联网架构小马的博客 292

Java lock锁的一些细节

前言 lock是Java接口,采用乐观锁的设计思想,采用CAS操作来实现的一个锁,这几点跟synchronized不同,synchronized原始采用的是CPU悲观锁机制, 参考博客 深入Lock锁底层原理实现,手写一个可重入锁 ...

笔记小屋 1468

再造轮子?有了synchronized为何还要提供Lock?

写在前面 在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是不是重复造轮子,多此一举呢?今天,我们就一起来探讨下这个问题。 再造轮子? 既然JVM中提供了synchronized关键字来保证只有一个线程能够访问同步代码块,为何还要提供Lock接口呢?这是在重复造轮子吗?Java的设计者们为何要这样做呢?让我们一起带着疑问往下看。 为何提供Lock接口? 很

Java圈全能架构师的博客 432

Java synchronized与Lock

synchronized和Lock锁是java并发编程中两大利器,可以用来解决线程安全的问题。但是为什么Java有了synchronized之后还是提供了Lock接口这个api,难道仅仅只是重复造了轮子这么简单么?本文就来探讨一下这个问题。 谈到这个问题,其实很多同学第一反应都会说,Lock锁的性能比synchronized好,synchronized属于重量级的锁。但是在JDK 1.6版本之后,JDK对synchronized进行了一系列性能的优化,synchronized的性能其实有了大大的提升(如果

一瓶绿茶三元钱 1487

为什么synchronized是非公平锁_再造轮子?有了synchronized为何还要提供Lock?

写在前面在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是不是重复造轮子,多此一举呢?今天,我们就一起来探讨下这个问题。再造轮子?既然JVM中提供了synchronized关键字来保证只有一个线程能够访问同步代码块,为何还要提供Lock接口呢?这是在重复造轮子...

weixin_39610807的博客 98

为什么synchronized是非公平锁_为什么提供了synchronized,还要提供Lock呢?

前言:在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是不是重复造轮子,多此一举呢?是否是再造轮子?既然JVM中提供了synchronized关键字来保证只有一个线程能够访问同步代码块,为何还要提供Lock接口呢?这是在重复造轮子吗?Java的设计者们为何要这...

weixin_39933414的博客 201

阿里Java有了 synchronized,为什么还要提供 Lock

在 Java 中提供了 synchronized 关键字来保证只有一个线程能够访问同步代码块。既然已经提供了 synchronized 关键字,那为何在 Java 的 SDK 包中,还会提供 Lock 接口呢?这是不是重复造轮子,多此一举呢?今天,我们就一起来探讨下这个问题。 再造轮子? 既然 JVM 中提供了 synchronized 关键字来保证只有一个线程能够访问同步代码块,为何还要提供 Lock 接口呢?这是在重复造轮子吗?Java 的设计者们为何要这样做呢?让我们一起带着疑问往下看。 为何提

m0_67698950的博客 133

为什么synchronized是非公平锁_面试官:Java提供了synchronized,为什么还要提供Lock呢?...

写在前面在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块。既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是不是重复造轮子,多此一举呢?今天,我们就一起来探讨下这个问题。再造轮子?既然JVM中提供了synchronized关键字来保证只有一个线程能够访问同步代码块,为何还要提供Lock接口呢?...

weixin_39999116的博客 225
上一篇: 谈谈 Java HTTP 基本认证
下一篇: 详解Java关键字之 volatile
JavaMonsterr
博客等级 码龄4年 211粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值