前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >synchronized与Lock 擂台之战

synchronized与Lock 擂台之战

作者头像
用户1260737
发布于 2018-01-31 03:24:51
发布于 2018-01-31 03:24:51
7540
举报
文章被收录于专栏:趣谈编程趣谈编程

面试官:说说synchronized和Lock(或ReentrantLock)的区别

Java 1.5之后,对共享变量访问的协调机制除了之前的synchronized和volatile又多了一个Lock,深刻理解synchronized与Lock,并熟悉两者的应用场景对编写并发程序有着非常重要的作用

部落新添大将

话说JDK1.5之前,并发部落 synchronized 和 volatile 可谓红人,无人不知,无人不晓

当多个线程访问同一共享变量时,只需在操作该共享变量的方法上加一个synchronized,就可以保证同一时刻只有一个线程操作该共享变量(还有其他用法)

这使得多个线程按照要求合理的占用和释放资源,所以并发部落如此昌盛,synchronized 功不可没

JDK1.5的到来,打破了这种局面

一个名为Lock的接口出世,听说这个Lock刚出世就神通广大,不仅有着和synchronized一样的功能,在锁的获取上还可以定时获取,轮询获取和可中断获取等等一系列高级的技能

这消息传到了synchronized的耳中,心中很是不爽,决定找个擂台与Lock一决胜负,可是想到Lock有那么多的优势,自己心中顿时没了底气,所以他决定对自己升级一下再去PK

synchronized找到了JDK老大诉苦,说要改造改造自己

JDK老大说道:“之前一直有人抱怨你慢,因为线程要获得锁和释放锁都要进行一次重量级的系统调用,我早都想着给你优化优化”

“好啊好啊”,synchronized说道

“其实我这里已经有方案了,你暂且回去,等JDK1.6的到来吧”JDK回道

“好的”,synchronized回复到。

新synchronized问世

终于JDK1.6到来了,synchronized在锁的获取和释放上有了重大改进,引入了偏向锁、轻量级锁和重量级锁,这次synchronized信心大增,决定去找Lock PK

synchronized 到了 Lock 跟前,说道:“久闻Lock兄神通广大,今日一见,不知神通在何处?”

Lock 一看这家伙是来挑事的,自己也不甘示弱,“神通之处你自然看不出来,用时方显神通”,Lock回应道

synchronized气的咬牙切齿,但这也正和自己心意,“哦,那我想见识见识,明日部落有一场擂台比武,不知Lock兄能否夺得桂冠”

“那是必然”,Lock回应道

“那明日一决雌雄”,synchronized甩下一句就走了

擂台比武

次日,两人都来到了擂台旁,并发部落的人几乎都来了,都想看看synchronized和Lock的好戏

用法PK

synchronized说道:“首先我是一个关键字,我常常被人称为内置锁,我的使用特别简单,如果你想让某一个方法在同一时刻只能由一个线程访问,那么只需要在方法上加上一个synchronized,如下:

这样对变量 i 的修改就线程安全了”

synchronized说道,“对了,更为让人清爽的是,我的加锁和释放锁都是隐式的,不需要程序员们在代码层次上手动的去加锁和释放锁,是不是很优雅?”

听完synchronized的一番自述后,虽说在用法上稍逊synchronized,但是Lock也不甘示弱,说道:

“我是一个接口,可以有无数的子类去实现我,ReentrantLock就是一个

我的使用也很简单呀,当你想给某一段代码加锁的话,只需要在代码块之前调用 lock() 方法,在之后调用 unlock() 不信你看”:

虽说加锁和释放锁都要在代码层次上显示的去操作,稍复杂一些,不是很优雅,但是我的锁获取和释放更加灵活

比如说有一个先获取锁A,再获取锁B,获取锁B之后释放锁A,然后再释放锁B的需求,我想什么时候获取锁和释放锁,直接调用 lock()unlock() 就OK了

Lock拿出自己的优势来弥补了一下自己的不足

性能PK

早有准备的synchronized暗自窃喜,在这方面现在自己不比Lock差,synchronized说道,“性能这块我现在引入了偏向锁,轻量级锁和重量级锁,这些改变我的性能比之前提高了许多”

“提高了许多现在才和我差不多”Lock 插了一刀,气的synchronized无话可说

用途PK

synchronized这块很是心虚,论用途,Lock比自己多,但是自己还是心理给自己打气,说道:

“并发控制这块的需求,基本上我都可以解决,而且用法很优雅,许多程序员已经习惯了我的存在,并且在发生异常的时候,JVM老大会自动释放锁,这样就避免了死锁的产生”

synchronized抓住Lock一定要调用 unlock() 方法释放锁的缺点不放

“不像有些人,如果不主动 调用 unlock() 释放锁,就很可能造成死锁”,synchronized又补了一句

Lock立马回应道:

“我虽有些许不足,但是我的高级功能很强大,synchronized可以实现的功能我都可以实现,除此之外,我还有 等待可中断可实现公平锁以及锁可以绑定多个条件等高级功能”

台下的观众眼中放光,特别想听听这些都是什么东西,之前都没见过

只见Lock清了清嗓门,一个一个的解释起来了

① 所谓等待可中断就是一个线程去获得一个锁的时候,由于很长时间没有获取到锁,可以放弃等待,处理其他事情

比如有两个线程 A 和 B,A获得了锁,B想获得该锁,那么B线程就挂起了

如果A迟迟不肯放锁,当该锁的获取是可以响应中断(调用lock.lockInterruptibly()),那么当其他线程中断该线程的时候,则B线程就可以响应中断,去做其他事情了

//在获取锁时被中断,抛出 InterruptedException

lock.lockInterruptibly()

如下图:

run() 方法是 B 线程(继承了Thread)的方法,如果不想让B线程等待,只需要让其他线程调用 B 线程的 interrupt() 方法,就会进入到 catch 并执行下面的任务

不必要在read函数的获得锁上一直阻塞等待(一直阻塞等待是因为B线程它一直想获得A线程的所持有的锁,但是迟迟没有得到)

②可实现公平锁:所谓公平锁,就是在多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁

比如A先来获得锁,获取失败,阻塞等待,然后B来获取锁,获取失败,阻塞等待,最后当这个锁释放的时候,按照公平锁的原则,A肯定会得到锁在ReentrantLock的构造函数中,可以传入是否为公平锁的参数,如:

// 使用公平锁机制

Lock lock = new ReentrantLock(true);

③ 所谓 锁绑定多个条件是指,一个 ReentrantLock 对象可以绑定多个 Condition对象(通过 lock.newCondition 创建一个Condition)

比如现在有两个方法methodA和methodB,有两个线程阻塞在methodA上,有一个线程阻塞在methodB上,现在想单独唤醒methodA上的线程 或者单独唤醒阻塞在methodB上的线程

如果是wait()和notify或notifyAll() 机制,则需要两个锁而ReentrantLock只需要一把锁就可以完成,一把锁可以new 多个Condition

在调用 lock.lock() 后 可以调用 Condition 的 await() 方法使线程处于等待状态,释放锁,如下:

当有两个线程进入methodA时,一个获得锁[ lock.lock() ]后又释放锁[ conditionA.await() ],进入等待状态

另一个线程同样也进入等待状态,当其他线程调用 conditionA.signalAll() [也可调用 conditionA.signal() ] 的时候,可以唤醒在conditionA上等待的所有线程:如下

这样,在conditionA上等待的线程就被全部唤醒了,这和 notifyAll() 的作用一样,只是这里的condition 可以由一个 lock 创建很多

同样的也可以在methodB中使用 conditionB, 最后用 conditionB.signalAll() 来唤醒在 conditionB 上等待的所有线程

如果是wait 和 notify 的话,就需要多个锁了

听完Lock的自述后,大家都赞不绝口,地下一片掌声

最后的胜负

这时候裁判大人出场了,听完两位大侠的叙述,我看两人各有优缺

synchronized 为许多开发人员所熟悉,并且简洁紧凑,许多现有的程序都已经使用了synchronized

而 Lock 有许多高级功能,在一些特定的场合能派上大用处,但是Lock的危险性很高,如果忘记在finally块中调用 unlock,那么就埋下了一颗定时炸弹

所以只有当synchronized 不能满足需求时,才可以使用ReentrantLock

现在我宣布,synchronized 略胜一筹,但Lock也是很不错的

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 趣谈编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
云上部署Python3爬虫--以腾讯云+Ubuntu为例
Xshell学生和家用是免费的, 下载地址http://www.netsarang.com/download/free_license.html
FesonX
2018/06/07
2.4K0
服务器上部署scrapy爬虫项目
爬爬们,如果你已经开始部署项目了,那么你肯定也已经写好了完整的爬虫项目,恭喜你,你很优秀! **今天忙了小半天的服务器部署,跟大家分享一些心得~
py3study
2020/01/02
1.3K0
drf项目部署到腾讯云
在购买了腾讯云服务器成功之后,腾讯云的站内信会将系统的登录名:Ubuntu,以及登录初始密码发给你。
玩蛇的胖纸
2019/07/01
4.7K0
drf项目部署到腾讯云
python3 部署
前几天去听了北京python-conf,老师们都在宣传python3的各种好处,和自力讨论之后,决定把自己的小项目都升级到python3。其实代码改起来还好,因为都是比较小的项目,问题主要卡在部署。我使用的云服务器都是ubuntu14.04的,上面默认的python3是3.4版本,而我本地的是3.6.3版本。虽然目前没问题,但为将来起见,以及为了让本地开发和线上的python版本尽量一致,故尝试在服务器上也用3.6.3的版本。
py3study
2020/01/06
6370
Django线上部署教程:腾讯云+Ubuntu+Django+Uwsgi
终于将Django成功部署到了腾讯云上,也实现了HTTPS的功能。现将步骤方法,部署环境一一列举如下,方便日后查看。
用户2416682
2019/09/27
2.9K0
Django线上部署教程:腾讯云+Ubuntu+Django+Uwsgi
腾讯云GPU服务器部署Ai绘画Stable Diffusion 小白可用
一、服务器购买 本人本地是个win10的PC 安装了 显示GPU 算力不够,升级配置也需要钱 云服务商的选择上,很普通,大家随意选择腾讯云/移动云....都可以。我是之前用的腾讯云,在腾讯云上抢的GP
用户2878251
2023/04/15
5.7K0
Linux爬虫系统从开始到部署成功全流程
做过爬虫的都知道,很多公司都会有自己的专属技术人员以及服务器,通常情况下再部署爬虫前,首先要将准备好的inux服务器进行环境部署,并且要安装必要的爬虫技术栈,一切环境部署差不多了再去部署爬虫代码。下面就是我整理的一个真实案例,可以一起看看我从准到部署完成的具体流程。
华科云商小徐
2025/06/13
1140
小白学 Scrapy 爬虫系列之一:准备实验机器
编程派
2017/05/25
1.5K0
小白学 Scrapy 爬虫系列之一:准备实验机器
如何解决Python包依赖问题
以简洁高效(指编程较为高效, 而不是运行速度)出名的Python, 在包依赖问题上有时候让人挠头.
FesonX
2018/05/30
4.3K1
如何解决Python包依赖问题
使用腾讯云配置小程序Python开发环境
之所以选腾讯云的原因很简单,那就是便宜,选用成都区,最低配置每月只需29¥。在 腾讯云 官网注册登录就可以直接购买服务器了。服务器系统我选择的是 ubuntu。
goodspeed
2020/12/22
7.8K0
使用腾讯云配置小程序Python开发环境
django2+uwsgi+nginx上线部署到服务器Ubuntu16.04(最新最详细版)
1.前期准备 1.打开Terminal终端,执行以下命令,将项目所需要的依赖包,都记录到一个文件内备用。 pip freeze >requirements.txt 2.将项目文件夹→右键→添加压缩文件
玩蛇的胖纸
2018/07/04
1.7K0
腾讯云双十一活动:腾讯云轻量应用服务器快速搭建Python开发环境指南
双十一不仅仅是购物狂欢节,对于希望享受高性能云服务的企业和开发者而言,更是入手腾讯云产品的绝佳时机!然而,面对琳琅满目的产品与各种优惠活动,如何才能买到性价比最高的产品?本文将为你深入剖析腾讯云双十一的优惠机制,教你如何用最少的预算获取最佳的云服务配置,助你在年末冲刺中脱颖而出。
一键难忘
2024/11/10
6711
腾讯云双十一活动:腾讯云轻量应用服务器快速搭建Python开发环境指南
使用Flask在服务器实现一个API接口。
主要涉及到Python3、MySQL、Flask、Nginx、uwsgi这几个东西。
小F
2020/10/09
2K0
使用Flask在服务器实现一个API接口。
【Lighthouse教程】网页内容抓取入门
网页内容抓取(Web Scraping)是指通过网页抓取工具(即Web Crawler,亦称网页爬虫)对指定网页进行设定行为的自动访问,并进行数据分析提取、最终持久化至电子表格/数据库等存储的过程。此类工作对于科学研究、推荐系统设计、大数据挖掘分析、人工智能、商业分析等多类应用领域都是不可或缺的关键步骤。
溪歪歪
2020/06/15
7.1K5
【Lighthouse教程】网页内容抓取入门
Django+nginx+uwsgi部署教程(centos7+ubuntu16.4)
项目部署教程 在线教育平台项目演示地址 1.1.原理介绍 django  一个基于python的开源web框架 uwsgi  一是一个web服务器,也可以当做中间件 nginx 常用高性能代理服务器 wsgi.py django项目携带的一个wsgi接口文件 nginx Nginx是一个Http和反向代理服务器 什么是反向代理服务器呢? 正向的就是由浏览器主动的想代理服务器发出请求,经代理服务器做出处理后再转给目标服务器 反向的就是不管浏览器同不同意,请求都会经过代理服务器处理再发给目标服务器 这其中
zhang_derek
2018/04/24
1.4K0
Django+nginx+uwsgi部署教程(centos7+ubuntu16.4)
腾讯云Linux服务器搭建一个WordPress博客
看到网络上很多人买了腾讯云服务器后却不知道怎么搭建WordPress博客,看了一下腾讯云出的WordPress教程,我觉得对新手来说难度还是太大了,所以就根据自己的建站经历写了一篇,本文采用腾讯云服务器CVM+宝塔管理面板+WordPress的方式搭建,力求简单易懂,希望能帮助到需要的朋友们。
用户5907306
2019/08/08
7.9K0
腾讯云Linux服务器搭建一个WordPress博客
(20211206更新)ubuntu18.04 安装Python3.8.3、jupyter notebook远程连接配置、虚拟环境搭建。及torch、tensorflow成功下载[通俗易懂]
但是吧,后续的pip install 会出现异常, 报错内容subprocess.CalledProcessError: Command ‘(‘lsb_release’, ‘-a’)’ 然后会看到有的会说将什么文件复制到什么地方。然后将系统的python文件夹中的所有py36 改为py38 。确实在某些操作上是行得通,但是在后续的折腾过程中还是出现了各种问题。所以现在抛弃这种了。 当然,可能也有看到有些博主会让你们进行优先级的选择,如下图所示这样的对吧
全栈程序员站长
2022/09/10
1.8K0
(20211206更新)ubuntu18.04 安装Python3.8.3、jupyter notebook远程连接配置、虚拟环境搭建。及torch、tensorflow成功下载[通俗易懂]
Python3爬虫学习.md
(1) urllib 简单的爬取指定网站 (2) Scrapy 爬虫框架 (3) BeautifulSoup 爬虫解析
全栈工程师修炼指南
2020/10/23
8580
Python3爬虫学习.md
用 Python 写你的第一个爬虫:小白也能轻松搞定数据抓取(超详细包含最新所有Python爬虫库的教程)
用 Python 写你的第一个爬虫:小白也能轻松搞定数据抓取(超详细包含最新所有Python爬虫库的教程)
猫头虎
2025/06/02
2.1K0
用 Python 写你的第一个爬虫:小白也能轻松搞定数据抓取(超详细包含最新所有Python爬虫库的教程)
Centos安装python3并使用Nginx+Gunicorn+virtualenv+supervisor来部署django项目
安装必要工具 yum-utils ,它的功能是管理repository及扩展包的工具 (主要是针对repository)
緣來
2018/09/18
2.2K0
Centos安装python3并使用Nginx+Gunicorn+virtualenv+supervisor来部署django项目
推荐阅读
相关推荐
云上部署Python3爬虫--以腾讯云+Ubuntu为例
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档