b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Java面试必问-死锁终极篇(2)

电脑杂谈  发布时间:2019-07-05 23:12:29  来源:网络整理

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

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

时序图

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

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

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

final ExecutorService executorService = 
        Executors.newSingleThreadExecutor();
Future<Long> f1 = executorService.submit(new Callable<Long>() {
    public Long call() throws Exception {
        System.out.println("start f1");
        Thread.sleep(1000);//延时
        Future<Long> f2 = 
           executorService.submit(new Callable<Long>() {
            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;
    }
});

多线程死锁的例子_线程死锁例子_linux 线程死锁

在这个例子中,线程池的任务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

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 深雪早苗
      深雪早苗

      舍不得再怎么不舍终究还是要舍得

    • 马俊威
      马俊威

      还用问

    热点图片
    拼命载入中...