ReentrantLock - > lockInterruptibly()有时候不会检查中断状态吗?

时间:2013-05-13 09:25:50

标签: java multithreading locking

最近我一直用“ReentrantLock”重构我的项目以简化逻辑
一般的想法是:

1.“主”可运行线程自行运行
2.如果一切正常,主线程将在条件“nextStep”上等待 3.当发生错误时,方法“onCancel()”将被/在另一个线程中调用,迫使主线程抛出InterruptionExcpetion,因此关闭将发生

经过一些测试后,我发现了自己的方法:

doInterrupt(); 

从未按预期工作:强制主线程输入“InterruptedException”子句并退出循环。

UPDATE-2:
我已经向所有输出日志行添加了“被中断”的调试消息,如果结果中断状态被某个人“神秘地”清除了......

更新:
锁定和条件方法:



     lock.lockInterruptibly();
     condition.await();

似乎没有检查中断状态SOMETIMES? .... javadoc上写着:
    ......
    If the current thread: 
    has its interrupted status set on entry to this method; or 
    is interrupted while acquiring the lock, 
    then InterruptedException is thrown and the current thread's interrupted status is cleared. 
    ......

从日志中它可以看到类似于:


    [action] waiting for completion...: 1  [is-interrupted:false]
    >> DEBUG ---> will begin next loop     [is-interrupted:false]
    [action] reset for next iteration: 2   [is-interrupted:false]
    [action] cancelling...                 [is-interrupted:false]
    >> DEBUG ---> will interrupt           [is-interrupted:false]
    >> DEBUG ---> check.                   [is-interrupted:true]
    [action] waiting for completion...: 2  [is-interrupted:false]
    >> DEBUG ---> will begin next loop     [is-interrupted:false]
    [action] reset for next iteration: 3   [is-interrupted:false]
    [action] waiting for completion...: 3  [is-interrupted:false]
    >> DEBUG ---> will begin next loop     [is-interrupted:false]
    [action] reset for next iteration: 4   [is-interrupted:false]
    [action] waiting for completion...: 4
    >> DEBUG ---> will begin next loop
    [action] reset for next iteration: 5
    [action] waiting for completion...: 5
    >> DEBUG ---> will begin next loop
    [action] reset for next iteration: 6
    ...... and so on until i == max
    [info] main process has reached a finish state.

这基本上意味着中断信号丢失或不以某种方式处理...

有更好的方法吗?或至少修改我的代码逻辑?

任何多线程专家???

这是我的代码:

public class SBCSTaskEngine extends GenericEngine<SBCSTask> implements XListener {
    private final ReentrantLock     lock       = new ReentrantLock();
    private final Condition         nextStep   = lock.newCondition();
    private volatile Thread         main       = null;
    // something else ...

    // it's a runnable "MAIN"
    @Override
    protected void run() {
        try {
            main = Thread.currentThread();
            // some setting up... x is between 1 ~ 10000
            for (int i = 1; i <= max; i++) {
                lock.lockInterruptibly();
                // some work ...
                log("[action] waiting for completion...: " + i);
                // a very long wait (could be REALLY fast if task went south)
                nextStep.await();
                if (max == i) {
                    isNormalCompletion = true;
                } else {
                    log("[action] reset for next iteration:" + (i+1));
                    // some reset work...
                }
                lock.unlock();
            } // end of [for] loop
        } catch (InterruptedException e) {
            log("[event] process stopped by singal.");
        } finally {
            try { lock.unlock(); } catch (Throwable ignored) {}
        }
        log("[info] main process has reached a finish state.");
    }

    private void doInterrupt() {
        log(">> DEBUG ---> will interrupt");
        if (main != null)
            main.interrupt();
            log(">> DEBUG ---> check.");
    }

   /**
    * implement: XListener(series)
    * instruct main process to enter cancel sequence
    *
    * known-issue: duplicate call? sync on method? wait for risk evaluation
    */
    @Override
    public void onCancel() {
        log("[action] cancelling...");
        doInterrupt();
    }

   /**
    * implement: XListener(series)
    * proceed the main thread to next loop
    *
    * known-issue: signal might occur before all "memebers" could await on the condition (happen-before?), just take the chance for now...
    */
   @Override
   private void doNotifyNextStep() {
       try {
           lock.lockInterruptibly();
           log(">> DEBUG ---> will begin next loop");
           nextStep.signalAll();
       } catch (InterruptedException e) {
           doInterrupt();
       } finally {
           try { lock.unlock(); } catch (Throwable ignored) {}
       }
   }
} // end of [SBCSTaskEngine] class


更多信息:我使用的Java版本:

java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

1 个答案:

答案 0 :(得分:0)

仔细检查“process()”中使用的每一种方法后,结果发现有一种方法“吞下”InterruptionException意外...

简单地抛出异常,整个代码/类现在按预期工作~~~

非常感谢“@ hendalst”,他在我的帖子中评论过,让我修改所有可能的中断泄漏...正如你所说:“上面的代码工作”,根本原因的方法在评论区域内“//一些工作。 ..“我没有在这里张贴......
并感谢“@orionll”关于编码原则的建议