zoukankan      html  css  js  c++  java
  • Future机制用于并发编程时的死锁检测

    Netty源码里面有个类:DeadLockProofWorker,源码如下:

     public static final ThreadLocal<Executor> PARENT = new ThreadLocal<Executor>();
    
        public static void start(final Executor parent, final Runnable runnable) {
            if (parent == null) {
                throw new NullPointerException("parent");
            }
            if (runnable == null) {
                throw new NullPointerException("runnable");
            }
    
            parent.execute(new Runnable() {
                public void run() {
                    PARENT.set(parent);
                    try {
                        runnable.run();
                    } finally {
                        PARENT.remove();
                    }
                }
            });
        }
    
        private DeadLockProofWorker() {
            super();
        }

    假设有下面的代码:

     ChannelFuture f = AChannelHandlerContext.getChannel().write(res);  
         f.addListener(new ChannelFutureListener() {              
    @Override  
    public void operationComplete(ChannelFuture future) throws Exception {  
        future.await();//(1)Thread 1 waiting for itself to be done.    
     //ChannelFuture f is done only if this invoke returns.  
    });  
        f.await();//(2)Thead 2 wait for f to be done. 
     

    如果ChannelFuture没有死锁检测,那么这两个线程将永远处于死锁状态。

    Thread2 等待ChannelFuture f 完成,ChannelFuture f 必须把listener的代码跑完才会完成,而listener也在等待future完成,于是死锁就造成了。

    看如何用线程变量杜绝死锁。

    上述代码: AChannelHandlerContext.getChannel().write(res) 会把写的操作放到线程池里异步进行,并且是这样放进去的:

    DeadLockProofWorker.start(executor, ARunnable r).

    上面的代码在r运行的线程里面可以通过DeadLockProofWorker.PARENT.get()获取到executor,即一个非null的对象,如果在f.await()里面检测一下,就可以知道await是否在r的线程里面了:

     public ChannelFuture await() throws InterruptedException {
            ...
            checkDeadLock();
            ...      
            return this;
    }
    
     private static void checkDeadLock() {
            if (DeadLockProofWorker.PARENT.get() != null) {
                throw new IllegalStateException(
                        "await*() in I/O thread causes a dead lock or " +
                        "sudden performance drop. Use addListener() instead or " +
                        "call await*() from a different thread.");
            }
        }

    如果DeadLockProofWorker.PARENT.get() != null 成立,那么当前线程就是启动线程1,然后抛出异常避免死锁。

  • 相关阅读:
    Vim怎么批量处理文件将tab变为space
    猫狗模型代码
    googLeNet网络
    Alex网络
    搭建FTP服务器
    除非Microsoft FTP 服务(FTPSVC)正在运行,否则无法启动FTP站点。服务目前已停止
    FTP文件夹打开错误,Windows无法访问此文件夹
    win7系统中ftp服务器搭建方法(多图)
    windows server 2008服务器IIS绑定阿里云域名
    URL Routing
  • 原文地址:https://www.cnblogs.com/cwjcsu/p/8433073.html
Copyright © 2011-2022 走看看