lock()和lockInterruptible()都表示获取锁,唯一区别是,当A线程调用lock()或lockInterruptible()方法获取锁没有成功而进入等待锁的状态时,若接着调用该A线程的interrupt()方法中断该线程的等待:
  • 如果A线程是通过lock()获取锁失败而进入等待状态的:则A线程不会马上执行自己的interrupt()方法去中断等待,而是继续等待获取锁(同时把中断命令放入等待队列), 获取到锁之后才响应自己的interrupt()方法去中断等待(从等待丢列中拿出中断命令执行)。获取锁之后,若A线程没有处于等待状态而调用interrupt()方法,是不会发生任何事情的,若获取锁之后A刚刚好又进入了等待状态,则执行等待丢列中的中断命令就会让A抛出InterruptedException()异常去中断等待
  • 如果A线程是想通过lockInterruptible()获取锁失败而进入等待状态的:则A线程会马上响应自己的interrupt()方法抛出InterruptedException 异常去中断等待,此时在finally里处理该异常,从而接着执行其他的代码

使用lockInterruptible()获取锁的例子:

public class LockTest {
private Lock lock = new ReentrantLock();
public void doBussiness() {
String name = Thread.currentThread().getName(); try {
System.out.println(name + " 开始获取锁");
lock.lockInterruptibly();//获取锁,可以调interrupt()中断等待
System.out.println(name + " 得到锁");
System.out.println(name + " 开工干活");
for (int i=0; i<5; i++) {
Thread.sleep(1000);
System.out.println(name + " : " + i);
}
} catch (InterruptedException e) {
//用lockInterruptibly()获取锁,必须处理可能调用interrupt()而抛出的InterruptedException异常
System.out.println(name + " 被中断");
System.out.println(name + " 做些别的事情");
} finally {
try {
lock.unlock();
System.out.println(name + " 释放锁");
} catch (Exception e) {
System.out.println(name + " : 没有得到锁的线程运行结束");
}
}
} public static void main(String[] args) throws InterruptedException { LockTest lockTest = new LockTest(); Thread t0 = new Thread(
new Runnable() {
public void run() {
lockTest.doBussiness();
}
}
); Thread t1 = new Thread(
new Runnable() {
public void run() {
lockTest.doBussiness();
}
}
); // 启动线程t1
t0.start();
Thread.sleep(10);
// 启动线程t2
t1.start();
Thread.sleep(100);
// 线程t1没有得到锁,中断t1的等待
t1.interrupt();
}
}
#运行结果:
Thread-0 开始获取锁
Thread-0 得到锁
Thread-0 开工干活
Thread-1 开始获取锁
Thread-1 被中断 //线程t1用lockInterruptible()获取锁失败而进入等待时,主线程调用t1.interrupt()使该t1抛出异常从而中断等待
Thread-1 做些别的事情//t1中断等待后接着执行其他的代码
Thread-1 : 没有得到锁的线程运行结束
Thread-0 : 0
Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
Thread-0 : 4
Thread-0 释放锁

  

使用lock()获取锁的例子:

把上面第9行中lock.lockInterruptibly()改为lock.lock(),其他代码不变,则输出结果:

Thread-0 开始获取锁
Thread-0 得到锁
Thread-0 开工干活
Thread-1 开始获取锁 //t0已经获取到了锁,所以t1只能进入等待状态(线程没有获取到锁会进入等待状态)。因为t1是调用lock.lock()获取锁的,所以即便主线程调用t1.interrupt()方法,t1也不会马上响应中断(即抛出InterruptedException异常来中断自己的等待状态),而是直到拿到锁之后才会响应中断
Thread-0 : 0
Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
Thread-0 : 4
Thread-1 得到锁 //t0打印完后已经执行了lock.unlock()释放了锁,要不然t1是拿不到锁的。同时t0还没来得及执行上面第23行代码用System打印出“Thread-0 释放锁”,时间片就轮给了t1,所以这行代码是t1执行输出的
Thread-1 开工干活
Thread-1 被中断 //由于t1拿到锁后才会去响应中断,所以上面第13行Thread.sleep(1000)在t1拿到锁之后又让t1进入了等待状态,此时t1刚刚好执行响应中断,故抛出InterruptedException来异常响应中断
Thread-1 做些别的事情
Thread-0 释放锁
Thread-1 释放锁 //t0早就释放了锁,在这里重新获得了时间片进行打印操作

  

  

  

聊聊Lock接口的lock()和lockInterruptible()有什么区别?的更多相关文章

  1. java多线程(死锁,lock接口,等待唤醒机制)

    一.Lock接口 常用方法 Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能. 使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Tic ...

  2. java 线程(五)线程安全 Lock接口

    package cn.sasa.demo3; import java.util.concurrent.ExecutionException; public class ThreadDemo { pub ...

  3. Lock接口简介

    在Java多线程编程中,我们经常使用synchronized关键字来实现同步,控制多线程对变量的访问,来避免并发问题. 但是有的时候,synchronized关键字会显得过于沉重,不够灵活.synch ...

  4. 并发王者课-铂金1:探本溯源-为何说Lock接口是Java中锁的基础

    欢迎来到<并发王者课>,本文是该系列文章中的第14篇. 在黄金系列中,我们介绍了并发中一些问题,比如死锁.活锁.线程饥饿等问题.在并发编程中,这些问题无疑都是需要解决的.所以,在铂金系列文 ...

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

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

  6. 线程同步 Lock接口

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

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

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

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

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

  9. jdk1.5多线程Lock接口及Condition接口

    jdk1.5多线程的实现的方式: jdk1.5之前对锁的操作是隐式的 synchronized(对象) //获取锁 { } //释放锁 jdk1.5锁的操作是显示的:在包java.util.concu ...

随机推荐

  1. 程序语言与编程实践7-> Java实操4 | 第三周作业及思路讲解 | 异常处理考察

    第三周作业,可能是异常那一章当时没怎么听,此前也不怎么接触,感觉还挺陌生的. 00 第1题 00-1 题目 /* * To change this license header, choose Lic ...

  2. java concurrent 并发多线程

    Concurrent 包结构 ■ Concurrent 包整体类图 ■ Concurrent包实现机制 综述: 在整个并发包设计上,Doug Lea大师采用了3.1 Concurrent包整体架构的三 ...

  3. 实现一个函数功能:sum(1,2,3,4..n)转化为 sum(1)(2)(3)(4)…(n)?

    // 使用柯里化 + 递归function curry ( fn ) {  var c = (...arg) => (fn.length === arg.length) ?           ...

  4. Spring对DAO的支持?

    Spring对数据访问对象(DAO)的支持旨在简化它和数据访问技术如JDBC,Hibernate or JDO 结合使用.这使我们可以方便切换持久层.编码时也不用担心会捕获每种技术特有的异常.

  5. spring集成mongodb简单使用和测试方式

    @EnableMongoRepositories @ComponentScan(basePackages = "cn.example") @Configuration public ...

  6. 四种类型的数据节点 Znode?

    1.PERSISTENT-持久节点 除非手动删除,否则节点一直存在于 Zookeeper 上 2.EPHEMERAL-临时节点 临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与 zoo ...

  7. List、Set、Map 和 Queue 之间的区别?

    List 是一个有序集合,允许元素重复.它的某些实现可以提供基于下标值的常量 访问时间,但是这不是 List 接口保证的.Set 是一个无序集合.

  8. 你对 Spring Boot 有什么了解?

    事实上,随着新功能的增加,弹簧变得越来越复杂.如果必须启动新的 spring 项 目,则必须添加构建路径或添加 maven 依赖项,配置应用程序服务器,添加 spring 配置.所以一切都必须从头开始 ...

  9. 什么是 REST / RESTful 以及它的用途是什么?

    Representational State Transfer(REST)/ RESTful Web 服务是一种帮助计 算机系统通过 Internet 进行通信的架构风格.这使得微服务更容易理解和实现 ...

  10. memcached 和 MySQL 的 query ?

    cache 相比,有什么优缺点? 把 memcached 引入应用中,还是需要不少工作量的.MySQL 有个使用方便的 query cache,可以自动地缓存 SQL 查询的结果,被缓存的 SQL 查 ...