当使用synchronized关键词提供的内置锁时,只要线程没有获得锁,那么就会永远等待下去,然而Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。通过这种方式,也可以很有效地避免死锁。

还是按照之前的例子,时序图如下:

时序图

下面系统阐述一下死锁的定义:所谓死锁,就是多个进程循环等待它方占有的资源而无限期的僵持下去的局面。这时,两个进程都被阻塞,并且保持下去,这种状况就是死锁(deadlock).。死锁是指多个进程在运行过程中,因为争夺资源而造成的一种僵局,如果没有外力推进,处于僵局中的进程就无法继续执行。

死锁条件里面的竞争资源,可以是线程池里的线程、网络连接池的连接,中数据引擎提供的锁,等等一切可以被称作竞争资源的东西。

用个例子来看看这个死锁的特征:

final ExecutorService executorService =

Executors.newSingleThreadExecutor();

Future f1 = executorService.submit(new Callable() {

public Long call() throws Exception{

System.out.println("start f1");

Thread.sleep(1000);//延时

Future f2 =

executorService.submit(new Callable() {

public Long call() throws Exception{

System.out.println("start f2");

return -1L;

}

});

System.out.println("result" + f2.get());

System.out.println("end f1");

return -1L;

}

});

在这个例子中,线程池的任务1依赖任务2的执行结果,但是线程池是单线程的,也就是说任务1不执行完,任务2永远得不到执行,那么因此造成了死锁。原因图解如下:

线程池死锁

执行jstack命令,可以看到如下内容:

"pool-1-thread-1" prio=5 tid=0x00007ff4c10bf800 nid=0x3b03 waiting on condition [0x000000011628c000]

java.lang.Thread.State: WAITING (parking)

at sun.misc.Unsafe.park(Native Method)

- parking to wait for <0x00000007ea51cf40> (a java.util.concurrent.FutureTask$Sync)

at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)

at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)

at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:994)

at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1303)

at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:248)

at java.util.concurrent.FutureTask.get(FutureTask.java:111)

at com.test.TestMain$1.call(TestMain.java:49)

at com.test.TestMain$1.call(TestMain.java:37)

at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)

at java.util.concurrent.FutureTask.run(FutureTask.java:166)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

可以看到当前线程wait在java.util.concurrent.FutureTask对象上。

解决办法:扩大线程池线程数 or 任务结果之间不再互相依赖。

作者开始在muduo/base中封装了和网络无关的一些操作,如日志、时间、队列、互斥量、条件变量、线程、线程池等,给后面网络库的设计带来了极大便利。同步嵌套是产生死锁的常见情景,从上面的代码中我们可以看出,当t1线程拿到锁a后,睡眠2秒,此时线程t2刚好拿到了b锁,接着要获取a锁,但是此时a锁正好被t1线程持有,因此只能等待t1线程释放锁a,但遗憾的是在t1线程内又要求获取到b锁,而b锁此时又被t2线程持有,到此结果就是t1线程拿到了锁a同时在等待t2线程释放锁b,而t2线程获取到了锁b也同时在等待t1线程释放锁a,彼此等待也就造成了线程死锁问题。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候,死锁会让你的程序挂起无法完成任务。

// 连接1

final MultiThreadedHttpConnectionManager connectionManager1 = new MultiThreadedHttpConnectionManager();

final HttpClient httpClient1 = new HttpClient(connectionManager1);

httpClient1.getHttpConnectionManager().getParams().setMaxTotalConnections(1); //设置整个连接池最大连接数

// 连接2

final MultiThreadedHttpConnectionManager connectionManager2 = new MultiThreadedHttpConnectionManager();

final HttpClient httpClient2 = new HttpClient(connectionManager2);

httpClient2.getHttpConnectionManager().getParams().setMaxTotalConnections(1); //设置整个连接池最大连接数

ExecutorService executorService = Executors.newFixedThreadPool(2);

executorService.submit(new Runnable() {

public void run(){

try {

PostMethod httpost = new PostMethod("http://www.baidu.com");

System.out.println(">>>> Thread A execute 1 >>>>");

httpClient1.executeMethod(httpost);

Thread.sleep(5000l);

System.out.println(">>>> Thread A execute 2 >>>>");

httpClient2.executeMethod(httpost);

System.out.println(">>>> End Thread A>>>>");

} catch (Exception e) {

// ignore

}

}

});

executorService.submit(new Runnable() {

public void run(){

try {

PostMethod httpost = new PostMethod("http://www.baidu.com");

System.out.println(">>>> Thread B execute 2 >>>>");

httpClient2.executeMethod(httpost);

Thread.sleep(5000l);

System.out.println(">>>> Thread B execute 1 >>>>");

httpClient1.executeMethod(httpost);

System.out.println(">>>> End Thread B>>>>");

} catch (Exception e) {

// ignore

}

}

});

整个过程图解如下:

连接池死锁

在死锁产生后,我们用jstack工具查看一下当前线程堆栈信息,可以看到如下内容:

"pool-1-thread-2" prio=5 tid=0x00007faa7909e800 nid=0x3b03 in Object.wait() [0x0000000111e5d000]

java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x00000007ea73f498> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)

at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.doGetConnection(MultiThreadedHttpConnectionManager.java:518)

- locked <0x00000007ea73f498> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)

at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.getConnectionWithTimeout(MultiThreadedHttpConnectionManager.java:416)

at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:153)

at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)

at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)

at com.test.TestMain$2.run(TestMain.java:79)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)

at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)

at java.util.concurrent.FutureTask.run(FutureTask.java:166)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

"pool-1-thread-1" prio=5 tid=0x00007faa7a039800 nid=0x3a03 in Object.wait() [0x0000000111d5a000]

java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x00000007ea73e0d0> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)

at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.doGetConnection(MultiThreadedHttpConnectionManager.java:518)

- locked <0x00000007ea73e0d0> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)

at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.getConnectionWithTimeout(MultiThreadedHttpConnectionManager.java:416)

at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:153)

at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)

at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)

at com.test.TestMain$1.run(TestMain.java:61)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)

at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)

at java.util.concurrent.FutureTask.run(FutureTask.java:166)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

当然,我们在这里只是一些极端情况的假定,假如线程在使用完连接池之后很快就归还,在归还连接数后才占用下一个连接池,那么死锁也就不会发生。

在我的理解当中,死锁就是“两个任务以不合理的顺序互相争夺资源”造成,因此为了规避死锁,应用程序需要妥善处理资源获取的顺序。

聊到计算视觉及时下对这项技术的主流应用,黄博士说“计算视觉是一个从二维世界往三维世界的一个逆过程,实际上是一个病态问题。即官方rar应用自带的性能测试,测试模拟解压缩环境下cpu的处理速度(因为规避闪存影响没有实际调用i/o),亮点是可以随意设定线程数,耗时较短只有1分钟而且不在很多厂商的白名单里面。在实际进行中,针对当前酒店婚宴上菜过程中所存在的问题,需要做到:在上菜时,需要与司仪提前做好沟通,当司仪宣布婚宴开始后,此时厨师长就需要及时下达命令开始上菜,相应传菜生提前做好准备,一声令下后就要依次分区进行上菜。

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-110757-2.html

java死锁2_Java面试必问-死锁终极篇(2)相关推荐

  1. 看完946页“JAVA高级架构面试必问”,金九银十社招全拿下

    前言 我本科毕业后在老东家干了两年多,老东家算是一家"小公司"(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思报出身),毕业这两年多我也没有在大厂待过,因此找坑的时 ...

  2. Java年薪30W+面试必问知识之《2020年面试宝典总纲》

    前言 一份月薪30K的java开发岗位工作要求是怎样的呢?面试都会问到哪些呢? 任职要求: 1.计算机或相关专业本科(或以上)学历,具备3年以上Java服务端开发经验,熟悉常用的Java开源框架,如熟 ...

  3. 『图解Java并发』面试必问的CAS原理你会了吗?

    在并发编程中我们都知道i++操作是非线程安全的,这是因为 i++操作不是原子操作. 如何保证原子性呢?常用的方法就是加锁.在Java语言中可以使用 Synchronized和CAS实现加锁效果. Sy ...

  4. 面试必问一:Java 中 == 和 equals 的区别你知道吗

    面试必问一:Java 中 == 和 equals 的区别你知道吗 前言 关于这个问题,一般初中级面试中都会遇到,还记得我当初实习找工作的时候也遇到了这个问题,现在都还记得自己是怎么回答的:== 是基本 ...

  5. java中的静态、动态代理模式以及Spring中的CgLib动态代理解读(面试必问)

    java中的静态.动态代理模式以及Spring中的CgLib动态代理解读(面试必问) 静态代理 动态代理 CgLib动态代理     基础知: 反射知识 代理(Proxy)是一种设计模式,提供了对目标 ...

  6. Java面试必问!javasocket服务端持久化

    前言 最近刷到了一句耐人寻味的话,"解决雪崩问题的最好办法是不发生雪崩". 不论是在硅谷互联网公司里还是在国内的互联网平台上,曾多次遇到过海量规模的交易瞬间吞噬平台的悲惨故事. 核 ...

  7. Java 面试必问题目,Java 后端校招面试题

    字节跳动一面: 自我介绍,主要讲讲做了什么和擅长什么 看你项目做 Spring 比较多, 问一下 Spring 相关的东西, IoC 是什么概念? Bean 的默认作用范围是什么?其他的作用范围? 索 ...

  8. 互联网公司面试必问的mysql题目(上)

    又到了招聘的旺季,被要求准备些社招.校招的题库. 介绍:MySQL是一个关系型数据库管理系统,目前属于 Oracle 旗下产品.虽然单机性能比不上oracle,但免费开源,单机成本低且借助于分布式集群 ...

  9. linux驱动工程面试必问知识点

    linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...

最新文章

  1. Blender与UE5完美结合全流程创作游戏资产视频教程
  2. 《疯狂Java讲义》7
  3. VTK:反射用法实战
  4. Javascript基础系列之(五)条件语句(比较操作符)
  5. 手动通过tomcat加载一个war项目。
  6. [Java基础]List集合子类特点
  7. html文本弹性,HTML5 很有趣的文本蹦床/弹性弯曲动效
  8. mysql 创建索引 终止_技术分享 | 常见索引问题处理
  9. for input string:是什么原因出现的_「汽车空调异味」周期性出现:原因是什么呢?...
  10. MSN Messenger协议简介
  11. Directx工具修复工具,专注修复C++动态链接DLL文件
  12. 8647服务器装系统,今天重新安装了系统,麻烦请红夜鬼先生进来帮我看一下
  13. html不支持lang属性,html的lang属性学习笔记
  14. 知乎高赞!怎么自学 python,大概要多久?
  15. 三防产品外观设计要点
  16. 【Pinia】小菠萝的使用
  17. 【VA 视频软件】(壹) TheoraConverter.NET
  18. MapBoxMap 之 定位
  19. 完美解析解决java.sql.SQLException:Access denied for user ‘‘@‘localhost‘ (using password: NO)
  20. Unity中的RectTransform

热门文章

  1. 【Elasticsearch】在Elasticsearch中查询Term Vectors词条向量信息
  2. 【hortonworks/registries】Parameter Schema name is null
  3. Memcache图形化管理工具MemAdmin
  4. 95-30-025-java.util-AbstractMap
  5. 95-190-454-源码-window-Trigger-Flink 自定义trigger
  6. 60-008-022-使用-命令-yarn-session命令
  7. 20-190-092-安装-Flink集群安装 flink-1.9.0 On Yarn
  8. Spring :Sprin体系
  9. Oracle : 使用JDBC连接ORACLE的三种URL格式
  10. 又一款神器:半小时带你轻松上手k8s