参考文献:https://www.cnblogs.com/cloudblogs/p/6440160.html

一、synchronize修饰不同代码都是锁住了什么?
大家都知道synchronize可以修饰属性、代码块,方法、类,但是修饰不同的代码锁住的内容是不同的。
1、修饰非静态属性和方法时,拿到的是调用这个方法或者属性的对象(this)的锁
2、synchronize()修饰代码块时,拿到的是指定对象的锁
3、修饰类、静态方法、静态代码块时,由于没有this指针,因此拿到的是类锁,也就是该类的class对象
!!!注意:一个对象只有一个锁
 
二、关于synchronize
由于synchronize是由JVM实现的,因此当加锁代码出现异常时,对象锁可以由JVM释放,包含以下三种情况:
1、 占有锁的线程执行完了代码块,然后释放对锁的占有;
2、 占有锁的线程发生了异常,此时JVM会让线程自动释放锁;
3、 占有锁的线程调用了wait()方法,从而进入了WAITING状态需要释放锁。
 
三、关于Lock

由于Lock是由JDK实现的,所以不像synchronize锁的获取和释放都是由JVM控制的,Lock的获取和释放都需要手动进行,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生

1、lock() 获取锁与释放锁 ,如果锁已被其他线程获取,则进行等待。

1 Lock lock = ...; lock.lock();
2 try{
3    //处理任务
4 }catch(Exception ex){
5 }finally{
6 lock.unlock(); //释放锁
7 }

2、tryLock() 获取锁时有返回值可以得知获取锁操作是否成功

 1 Lock lock = ...;
2 if(lock.tryLock()) {
3 try{
4 //处理任务
5    }catch(Exception ex){
6 }finally{
7 lock.unlock(); //释放锁
8   }
9 }else {
10 //如果不能获取锁,则直接做其他事情
11 }

如果获取成功则返回True,如果锁被其他线程占用则返回FALSE,该方法会立即返回结果不会让线程一直处于等待状态

3、tryLock(long time,TimeUnit unit) 与tryLock() 类似,但是与tryLock立即返回结果不同,该方法在拿不到锁的情况下回等待time时间,如果在限定时间内还是拿不到锁就返回FALSE,如果在一开始或者等待时间内拿到锁则返回TRUE。

4、lockInterruptibly()

通过这个方法尝试获取锁时,如果线程正在等待获取锁,则该线程可以响应Thread.interrupt()中断。synchronize对于没有获得锁处于等待状态的线程无法响应中断。

1 public void method() throws InterruptedException {
2 lock.lockInterruptibly();
3 try { //..... }
4 finally { lock.unlock(); }
5 }

lockInterruptibly方法必须放在try块中或者在调用lockInterruptibly的方法外声明抛出InterruptedException,推荐使用后者。

5、readWriteLock()

该锁提升了读操作的效率,不过要注意的是,如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程也会一直等待释放写锁。

四、Lock和synchronized的选择:
1、 Lock是一个接口,属于JDK层面的实现;而synchronized属于Java语言的特性,其实现有JVM来控制(代码执行完毕,出现异常,wait时JVM会主动释放锁)。
2、 synchronized在发生异常时,会自动释放掉锁,故不会发生死锁现(此时的死锁一般是代码逻辑引起的);而Lock必须在finally中主动unlock锁,否则就会出现死锁。
3、 Lock能够响应中断,让等待状态的线程停止等待;而synchronized不行。
4、 通过Lock可以知道线程是否成功获得了锁,而synchronized不行。
5、 Lock提高了多线程下对读操作的效率。
 
五、扩展
1、可重入锁:synchronized和ReentrantLock都是可重入锁。当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2。
 
2、可中断锁:等待获得锁的等待过程是否可以中断。通过上面的例子,我们可以得知Lock是可中断锁,而synchronized不是。
 
3、公平锁:尽量以请求的顺序来获取锁,同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该锁。synchronized是非公平锁,而ReentrantLock和ReentReadWriteLock默认情况下是非公平锁,但是可以设置成公平锁。
ReentrantLock lock = new ReentrantLock(true);
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
设置为TRUE即为公平锁,为FALSE或者无参数为非公平锁。
 
4、读写锁:读写锁将对临界资源的访问分成了两个锁,一个读锁和一个写锁。增加读写灵活性。即ReadWriteLock接口及其实现ReentrantReadWriteLock。

关于synchronize与lock的区别的更多相关文章

  1. Synchronize 和 Lock 的区别与用法

    一.synchronized和lock的用法区别 (1)synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要 ...

  2. 深入研究 Java Synchronize 和 Lock 的区别与用法

    在分布式开发中,锁是线程控制的重要途径.Java为此也提供了2种锁机制,synchronized和lock.做为Java爱好者,自然少不了对比一下这2种机制,也能从中学到些分布式开发需要注意的地方.  ...

  3. synchronize和lock的区别 & synchionzie与volatile的区别

    synchronized与Lock的区别 https://www.cnblogs.com/iyyy/p/7993788.html Lock和synchronized和volatile的区别和使用 ht ...

  4. 多线程---再次认识volatile,Synchronize,lock

    在多线程中我们常用的保证共享变量的方法有很多,现在我们介绍其中的一种,volatile,也是效率最高的一种.    一 .volatile的意义:             为了确保共享变量能被正确和一 ...

  5. synchronize、Lock、ReenTrantLock 的区别

    synchronize 和Lock: 1.synchronize 系java 内置关键字:而Lock 是一个类 2.synchronize 可以作用于变量.方法.代码块:而Lock 是显式地指定开始和 ...

  6. Java中synchronized和Lock的区别

    synchronized和Lock的区别synchronize锁对象可以是任意对象,由于监视器方法必须要拥有锁对象那么任意对象都可以调用的方法所以将其抽取到Object类中去定义监视器方法这样锁对象和 ...

  7. Java synchronized和 Lock 的区别与用法

    在分布式开发中,锁是线程控制的重要途径.Java为此也提供了2种锁机制,synchronized和lock.做为Java爱好者,自然少不了对比一下这2种机制,也能从中学到些分布式开发需要注意的地方.  ...

  8. (转)synchronized和lock的区别

    背景:最近在准备java基础知识,对于可重入锁一直没有个清晰的认识,有必要对这块知识进行总结. 1 . 什么是可重入锁 锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保 ...

  9. Synchronized和lock的区别和用法

    一.synchronized和lock的用法区别 (1)synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要 ...

随机推荐

  1. Part 38 AngularJS cancel route change

    n this video we will discuss, how to cancel route change in Angular with an example. This is extreme ...

  2. Part 11 to 20 Basic in C# continue

    Part 11-12 switch statement in C# switch statement break statement   if break statement is used insi ...

  3. vue + cesium开发(4) 绘制图形

    在官方例子中每个图形都是一个entity,官方例子提供了显示正方形.圆形.锥形.图片等多种案例! // 初始花 var viewer = new Cesium.Viewer("cesiumC ...

  4. [cf10E]Greedy Change

    对于$w$的表示方案,可以用序列描述,即$x_{i}$表示第$i$种货币的数量 贪心策略得到的方案即是(对应序列)字典序最大的方案,并定义最优策略得到的方案为在最小化货币总数的基础上,(对应序列)字典 ...

  5. [atARC071F]Infinite Sequence

    注意到当$a_{i}\ne 1$且$a_{i+1}\ne 1$,那么$\forall i<j,a_{j}=a_{i+1}$(证明的话简单归纳就可以了) 令$f_{i}$表示在题中条件下,还满足$ ...

  6. [loj2842]野猪

    首先,并不一定走"除了上一次来的边"以外的最短路,但考虑"除了上一次来的边"以外的最短路和次短路(这里的次短路指最后一条边与最短路不同的"最短路&qu ...

  7. idea中解决整合SSM加载不到dataSource;

    idea在搭建maven的ssm项目中注入dataSource报错解决方案: 在整合ssm时候,发现 dataSource加载不到,并报错:解决办法为:file–>project structu ...

  8. 9.1 k8s pod版本更新流程及命令行实现升级与回滚

    1.创建 Deployment root@k8-deploy:~/k8s-yaml/controllers/deployments# vim nginx-deployment.yaml apiVers ...

  9. Codeforces 79D - Password(状压 dp+差分转化)

    Codeforces 题目传送门 & 洛谷题目传送门 一个远古场的 *2800,在现在看来大概 *2600 左右罢( 不过我写这篇题解的原因大概是因为这题教会了我一个套路罢( 首先注意到每次翻 ...

  10. 如何从vcf文件中批量提取一系列基因的SNP位点?

    目录 需求 示例文件 代码实现 补充说明 需求 客户的一个简单需求: 我有一批功能基因位点,想从重测序的群体材料中找到这些位点,如何批量快速获得? 示例文件 gene.txt test.vcf 代码实 ...