java - ReentrantLock -> lockInterruptically() 有时不会检查中断状态?

标签 java multithreading locking

最近我一直在用“ReentrantLock”重构我的项目以简化逻辑。

总体思路是:

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

经过一番测试,得出了我自己的方法:

doInterrupt(); 

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

更新2:
我已经在所有输出日志行中添加了一条“被中断”调试消息,如果事实证明中断状态被某人“神秘地”清除了......

更新:
锁定和条件方法:



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

有时似乎没有检查中断状态? .... 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. 
    ......

from the log it could see something like:


    [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)

最佳答案

仔细检查“process()”中使用的每一个方法后,发现有一个方法不小心“吞噬”了InterruptionException...

只需抛出异常,整个代码/类现在就按预期工作了~~~

非常感谢“@hendalst”,他在我的帖子中发表了评论,使我修改了所有可能的中断泄漏......正如您所说:“上面的代码有效”,根本原因方法在评论区域内“//一些工作。 ..”我没有在这里发布...

并感谢“@orionll”关于编码原则的建议

关于java - ReentrantLock -> lockInterruptically() 有时不会检查中断状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16518706/

相关文章:

c# - 在单独的线程上引发事件

java - 同步方法是否会阻止对象字段被更新?

java - TreeMap 在刚刚更改的字段中返回空值

Java Rest 删除错误

java - Android 不会显示 PHP 页面的特殊字符

java - 我可以将 Arrays.fill 与二维数组一起使用吗?如果是这样,我该怎么做?

java - Swing 应用程序中音频线程的设计模式 : How to notify midi executor is shutdown to drive a GUI state-change?

c# - 多线程事件处理程序

c++ - 数据容器C++设计

java - Redis 为什么需要分布式锁