关于synchronized字段,不管该关键字是修饰方法还是修饰同步代码块,synchronzed拿到的都是对象。
当synchronized修饰的是方法时,synchronized所拿到的是调用该方法的对象的锁,一般情况下都是this的锁;
当synchronized()修饰的同步代码块时,synchronized拿到的是指定对象的锁。
 
扩展:
当synchronized修饰的静态方法时,由于静态方法不包含this,属于类层次的方法,所以,synchronized拿到的是这个方法所属Class对象的锁。
java中的对象每个只含有一个锁,通过synchronized来获取对象的锁。
 
注意:当方法异常退出时,其对象锁可以有JVM进行释放。
占有锁的线程释放锁时一般是以下三种情况:
1、 占有锁的线程执行完了代码块,然后释放对锁的占有;
2、 占有锁的线程发生了异常,此时JVM会让线程自动释放锁;
3、 占有锁的线程调用了wait()方法,从而进入了WAITING状态需要释放锁。
 
探究-->对象都含有什么锁?
对象锁:又称独占排它锁,通过名字我们便可知道,在多线程程序中,一旦一个线程到达了共享区(即synchronized修饰的区域)。那么该线程将拥有该共享区的对象锁,其他线程想要进入,只能等到该线程释放了锁才可进入。对应于非静态方法和非静态代码块。
类锁:方法或代码块所在类的类对象的锁。对应于静态方法和静态代码块。
 
 
Lock接口
体系类图:
方法介绍:
Lock:是Lock接口中使用最多的获取锁的方法,如果锁被其他线程占用就等待。由于Lock接口是基于JDK层面的,所以,锁的释放动作必须手动进行。不像synchronized是基于Java语言的特性,属于JVM层面,锁的获取和释放动作都由JVM自动进行,对开发者是透明的。
使用方式:
Lock lock = ...; lock.lock();
try{    
   //处理任务
}catch(Exception ex){
}finally{
    lock.unlock();   //释放锁
}
 
tryLock:表示用来尝试获取锁,如果获取成功即返回TRUE,如果锁被其他线程占用,则返回FALSE;该方法会立即返回结果,不会一直处于等待状态。
 
tryLock(long time,TimeUnit unit):与tryLock类似,区别在于这个方法在拿不到锁的情况下会等待一个时间time,在时间期限之内如果还拿不到锁,就返回FALSE;同时可以相应中断。如果在一开始或者等待期间获得了锁,则返回true。
问题:如果在开始没有拿到锁,那么代码块会进入到等待状态么?
猜想:我觉得会进入等待状态,不过在等待的这段时间内,会存在一个响应机制来监测别的线程是否释放了锁,如果释放了锁,则直接有该线程获取锁,该方法返回TRUE;如果没有释放,那么该方法将不再享有响应机制的提醒,并返回FALSE。
使用方式:
Lock lock = ...;
if(lock.tryLock()) {
     try{
         //处理任务     
   }catch(Exception ex){
     }finally{
         lock.unlock();   //释放锁     
  }
}else {   
  //如果不能获取锁,则直接做其他事情
}
lockInterruptibly:当通过这个方法尝试获取锁时,如果线程正在等待获取锁,那么这个线程能够响应中断,即被自己或者其他线程中断线程的等待状态。例如,当两个线程同时通过lock.lockInterruptibly()方法获取锁时,假如线程A获取了锁,那么线程B就只能进入等待状态,那么对线程B调用ThreadB.interrupt()能够中断线程B的等待状态。
 
注意:lockInterruptibly方法必须放在try块中或者在调用lockInterruptibly的方法外声明抛出InterruptedException,推荐使用后者。
 
使用方式:
public void method() throws InterruptedException {     lock.lockInterruptibly();     try {       //.....     }     finally {         lock.unlock();     }  }
疑问:释放掉线程的等待状态有什么用处?
相比于synchronized,等待状态的线程无法响应中断。提高了代码的灵活性,当不想持续的等待下去时,响应中断去做其余的事情,更具灵活性。
 
ReadWriteLock
该锁提升了读操作的效率,不过要注意的是,如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程也会一直等待释放写锁。
 
 
Lock和synchronized的选择:
1、 Lock是一个接口,属于JDK层面的实现;而synchronized属于Java语言的特性,其实现有JVM来控制。
2、 synchronized在发生异常时,会自动释放掉锁,故不会发生死锁现(此时的死锁一般是代码逻辑引起的);而Lock必须在finally中主动unlock锁,否则就会出现死锁。
3、 Lock能够响应中断,让等待状态的线程停止等待;而synchronized不行。
4、 通过Lock可以知道线程是否成功获得了锁,而synchronized不行。
5、 Lock提高了多线程下对读操作的效率。
 
扩展
可重入锁:synchronized和ReentrantLock都是可重入锁。当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2。
 
可中断锁:通过上面的例子,我们可以得知Lock是可中断锁,而synchronized不是。
 
公平锁:尽量以请求的顺序来获取锁,同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该锁。synchronized是非公平锁,而ReentrantLock和ReentReadWriteLock默认情况下是非公平锁,但是可以设置成公平锁
ReentrantLock lock = new ReentrantLock(true);
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
设置为TRUE即为公平锁,为FALSE或者无参数为非公平锁。
 
读写锁:读写锁将对临界资源的访问分成了两个锁,一个读锁和一个写锁。即ReadWriteLock接口及其实现ReentrantReadWriteLock。

Synchronized和Lock接口的更多相关文章

  1. 多线程里面的关键字,wait, notfiy, 锁(synchronized), lock接口

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  2. java多线程Lock接口简介使用与synchronized对比 多线程下篇(三)

    前面的介绍中,对于显式锁的概念进行了简单介绍 显式锁的概念,是基于JDK层面的实现,是接口,通过这个接口可以实现同步访问 而不同于synchronized关键字,他是Java的内置特性,是基于JVM的 ...

  3. 线程中synchronized关键字和lock接口的异同

    一.synchronized关键字 1.可以用来修饰代码块 synchronized (this) { // 同步的关键字 this 表示当前线程对象 if (num == 0) { break; } ...

  4. synchronized关键字,Lock接口以及可重入锁ReentrantLock

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  5. Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)

    1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...

  6. Java并发之synchronized关键字和Lock接口

    欢迎点赞阅读,一同学习交流,有疑问请留言 . GitHub上也有开源 JavaHouse,欢迎star 引用 当开发过程中,我们遇到并发问题.怎么解决? 一种解决方式,简单粗暴:上锁.将千军万马都给拦 ...

  7. JUC之Lock接口以及Synchronized回顾

    Lock接口 Synchronized关键字回顾: 多线程编程步骤(上): 创建资源类,在资源类创建属性和操作方法 创建多个线程,调用资源类的操作方法 创建线程的四种方式: 继承Thread 实现Ru ...

  8. 线程同步 Lock接口

    同步:★★★★★ 好处:解决了线程安全问题. 弊端:相对降低性能,因为判断锁需要消耗资源,产生了死锁. 定义同步是有前提的: 1,必须要有两个或者两个以上的线程,才需要同步. 2,多个线程必须保证使用 ...

  9. Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock

    在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...

随机推荐

  1. 关于使用idea工具debug时,断点颜色由红色变成灰色

    在使用断点调试的时候,发现断点由原来的红色变成灰色的,后来发现是由于错误操作将Debug断点t调试禁用了 ,只需要点击禁用按钮取消就可以了 

  2. FZU_DS_2019_SequenceList

    单选题 2-1   数组A[1..5,1..6]每个元素占5个单元,将其按行优先次序存储在起始地址为1000的连续的内存单元中,则元素A[5,5]的地址为:  A.1120      B.1125   ...

  3. MySQL基础语句(查询)

    students表 id class_id name gender score 1 1 小明 M 90 2 1 小红 F 95 3 1 小军 M 88 4 1 小米 F 73 5 2 小白 F 81 ...

  4. UE4中C++编程(一)

    一: C++工程和Gameplay框架 GameInstance 它适合放置独立于关卡的信息,比如说显示UI. GameMode 表示游戏玩法, 包含游戏进行的规则和胜利条件等等信息,游戏模式是和关卡 ...

  5. vue+node+mongondb实战之路由

    看了一段时间vue的文档,一直没有机会来开发一个真正的vue项目,趁着这几天清闲,整合一下最新的技术,变学变练来开发一个vue的简单博客 有了开发博客的想法之后,谁知道第一步就被拦住了,看了vue的基 ...

  6. [atARC125F]Tree Degree Subset Sum

    令$a_{i}$为$i$的度数-1,那么$(x,s)$合法即等价于存在$S\subseteq [1,n],|S|=x$且$\sum_{k\in S}a_{k}=s$ 引理:$(x,s)$合法的必要条件 ...

  7. 第02章_MySQL环境搭建

    第02章_MySQL环境搭建 1. MySQL的卸载 步骤1:停止MySQL服务 在卸载之前,先停止MySQL8.0的服务.按键盘上的"Ctrl + Alt + Delete"组合 ...

  8. 对于cmd命令的一些常用用法

    cmd命令是当今比较常见的主机命令,对于一些文件的执行和后台数据的控制有着比较有效的规范. 现在就讲几个比较常见的命令. IP查询 按住window+r 进入控制台,在输入cmd命令.在弹出的 cmd ...

  9. Redis线程模型的前世今生

    一.概述 众所周知,Redis是一个高性能的数据存储框架,在高并发的系统设计中,Redis也是一个比较关键的组件,是我们提升系统性能的一大利器.深入去理解Redis高性能的原理显得越发重要,当然Red ...

  10. Codeforces 1455G - Forbidden Value(map 启发式合并+DP)

    Codeforces 题面传送门 & 洛谷题面传送门 首先这个 if 与 end 配对的结构显然形成一个树形结构,考虑把这棵树建出来,于是这个程序的结构就变为,对树进行一遍 DFS,到达某个节 ...