synchronized和lock的使用分析(优缺点对比详解)
1.synchronized
加同步格式:
synchronized(需要一个任意的对象(锁)){
代码块中放操作共享数据的代码。
}
synchromized缺陷
synchronized是java中的一个关键字,也就是说是java语言的内置的特性。
如果一个代码块被synchronized修饰,当一个线程获取了对应的锁,并执行代码块时,其他线程只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:
(1)获取锁的线程执行完了改代码块,然后线程释放对锁的占有
(2)线程执行发生异常,此时JVM会让线程自动释放锁。
例子1:
如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。
因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过Lock就可以办到。
例子2:
当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。
但是采用synchronized关键字来实现同步的话,就会导致一个问题:
如果多个线程都只是进行读操作,当一个线程在进行读操作时,其他线程只能等待无法进行读操作。
因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。
另外,通过Lock可以知道线程有没有成功获取到锁。这个是synchronized无法办到的。
总的来说,也就是说Lock提供了比synchronized更多的功能。
2.lock
lock和synchronized的区别
(1)lock不是java语言内置的,synchronized是java语言的关键字,因此是内置特性。lock是一个类,通过这个类可以实现同步访问;
(2)lock和synchronized有一点非常大的不同,采用synchronized不需要用户手动的去释放锁,当synchronized方法或者代码块执行完毕之后,系统会自动的让线程释放对锁的占有,而lock则必须要用户去手动释放锁,如果没有主动的释放锁,就会可能导致出现死锁的现象
LOCK
首先要说明的就是,通过查看LOCK 的源码可知道,lock是一个接口
lock接口中每个方法的使用:lock()、tryLock()、tryLock(long time, TimeUnit unit)、lockInterruptibly()是用来获取锁的。 unLock()方法是用来释放锁的。
四个获取锁方法的区别:
(1)lock()方法时平常使用的最多的一个方法,就是用来获取锁的,如果锁已经被其他线程获取,则进行等待。
由于在前面讲到如果采用lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被释放掉,房主死锁的发生。
(2)tryLock()方法是有返回值的,他表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已经被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在哪里等待
(3)tryLock(long time, TimeUnit unit)方法和tryLock()方法时类似的,只不过区别在于这个方法在拿不到锁时会等待一定时间,在时间限制之内如果还是拿不到锁,就返回false。如果一开始就拿到锁或者在等待期间内拿到了锁,则就返回true。
(4)lockinterruptibly()方法比较特殊,当通过这个方法区获取锁时,如果线程正在等待获取锁,则这个线程能够相应中断,即中断线程的等待状态。也就是说,当连个线程同时通过lock.lockinterruputibly()向获取某个锁时,假如此时线程A获取到了锁,而线程B只有等待,那么对线程调用threadB.interrupt()方法能够中断线程B的等待过程。
注意:当一个线程获取了锁之后,是不会被interrupt()方法中断的
因此当通过lockinterruptibly()方法获取某个锁时,如果不能获取到,只有进行等待的情况下,是可以相应中断的
而用synchronized修饰的话,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。
ReentrantLock
直接使用lock接口的话,我们需要实现很多方法,不太方便,ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法,ReentrantLock,意思是“可重入锁”。
ReadWriteLock也是一个接口,在它里面只定义了两个方法:
一个用来获取读锁,一个用来获取写锁。也就是说将文件的读写操作分开,分成2个锁来分配给线程,从而使得多个线程可以同时进行读操作。ReentrantReadWriteLock实现了ReadWriteLock接口。
ReentrantReadWriteLock
ReentrantReadWriteLock里面提供了很多丰富的方法,不过最主要的两个方法:readlock()和writelock用来获取读锁和写锁
注意:
不过要注意的是,如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁。
3.LOCK和SYNCHRONIZED的选择
(1)lock是一个接口,而synchronized是java的关键字,synchronized是内置的语言实现;
(2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而lock在发生异常时,如果没有主动通过unlock()去释放锁,则很可能造成死锁现象,因此使用lock()时需要在finally块中释放锁;
(3)lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不讷讷狗狗响应中断
(4)通过lock可以知道有没有成功获取锁,而synchronized却无法办到
(5)lock可以挺高多个线程进行读操作的效率
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而竞争资源非常激烈是(既有大量线程同时竞争),此时lock的性能要远远优于synchronized。所以说,在具体使用时适当情况选择。
synchronized和lock的使用分析(优缺点对比详解)的更多相关文章
- vue和react全面对比(详解)
vue和react对比(详解) 放两张图镇压小妖怪 本文先讲共同之处, 再分析区别 大纲在此: 共同点: a.都使用虚拟dom b.提供了响应式和组件化的视图组件 c.注意力集中保持在核心库,而将其他 ...
- Android Telephony分析(五) ---- TelephonyRegistry详解
本文紧接着上一篇文章<Android Telephony分析(四) —- TelephonyManager详解 >的1.4小节.从TelephonyRegistry的大部分方法中: 可以看 ...
- Android Telephony分析(三) ---- RILJ详解
前言 本文主要讲解RILJ工作原理,以便更好地分析代码,分析业务的流程.这里说的RILJ指的是RIL.java (frameworks\opt\telephony\src\java\com\andro ...
- Android Telephony分析(二) ---- RegistrantList详解
前言 本文主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程.在Telephony模块中,在RIL.Tracker(ServiceStateTrac ...
- Windows8 各种版本区别对比详解
微软的 Windows8 操作系统提供了4个不同的版本,分别是 Windows RT.Windows 8 标准版.Windows 8 Pro 专业版 以及 Windows 8 Enterprise 企 ...
- 【集合框架】JDK1.8源码分析之ArrayList详解(一)
[集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...
- “全栈2019”Java第四十九章:重载与重写对比详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- nginx源码分析线程池详解
nginx源码分析线程池详解 一.前言 nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,n ...
- explain分析SQL语句详解
性能分析explain MySql Query Optimizer是MySql中专门负责优化select语句的优化器模块,主要功能:通过计算分析系统中收集到的系统信息,为客户端请求的Query提供他认 ...
随机推荐
- CentOS安Elasticsearch
工作中有需求用到es做数据分析和日志搜索的,整理记录一下安装部署过程.ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful we ...
- ARTS-2
ARTS的初衷 Algorithm:主要是为了编程训练和学习.每周至少做一个 leetcode 的算法题(先从Easy开始,然后再Medium,最后才Hard).进行编程训练,如果不训练你看再多的算法 ...
- python每日一练:0007题
第 0007 题: 有个目录,里面是你自己写过的程序,统计一下你写过多少行代码.包括空行和注释,但是要分别列出来. # -*- coding:utf-8 -*- import os def count ...
- 【Qt开发】【Linux开发】Qt程序在嵌入式设备(arm) 上运行,鼠标擦除界面的解决方案
笔者最近想在arm开发板上,开发一个应用程序,经过网上查询发现qt作为跨平台开发软件很不错,于是便选择了qt开发,笔者的qt版本是4.8.6的.由于arm的主频太低,在arm上进行开发编译,效率会大大 ...
- 如何在centos7中显示/etc/目录下以非字母开头,后面跟了一个字母及其它任意字符的文件或目录
ls /etc |grep "^[^[:alpha:]][[:alpha:]].*"
- 第9周总结&实验报告7
完成火车站售票程序的模拟. 要求:(1)总票数1000张:(2)10个窗口同时开始卖票:(3)卖票过程延时1秒钟:(4)不能出现一票多卖或卖出负数号票的情况.一:实验代码 package first; ...
- linux中防止黑客进入单用户模式进行强制修改密码窃取数据
如何防止别人恶意通过单用户系统破解root密码,进入系统窃取数据? 给grub加密,不让别人通过grub进入单用户. 当前系统:CentOS Linux release 7.6.1810 (Core) ...
- 【监控笔记】【1.2】监控事件系列——SQL Trace(默认跟踪与自定义跟踪)
目录: [1.1]概念与使用 [1.2]跟踪的基本操作 --[1.2.1]查看默认跟踪是否在运行 --[1.2.2]开启默认跟踪 --[1.2.3]关闭默认跟踪 --[1.2.4]查看跟踪文件/查看跟 ...
- 剑指Offer编程题(Java实现)——链表中倒数第k个结点
题目描述 输入一个链表,输出该链表中倒数第k个结点. 注意: 该题目不可以用先反转链表再输出第k个结点的方式,因为反转链表会改变该结点的next指向 思路一 使用栈Stack倒序存储,顺序pop第k个 ...
- 【暑假培训1】test1
T1: 30pts:直接暴力三层循环枚举 就就就先不写代码了qwq: 70pts: 因为X+Y+Z==0 所以我们可以考虑枚举X和Y,然后利用↑式子求出Z=-X-Y: 然后touli xcg的70pt ...