【问题标题】:lockInterruptibly Vs locklockInterruptively VS 锁
【发布时间】:2017-06-18 15:27:19
【问题描述】:

我无法区分。我读到这个:actual-use-of-lockinterruptibly-for-a-reentrantlock

并想对其进行测试。代码如下:

public class Test {
public static void main(String[] args){
    Test test = new Test();
    test.inturreptWork();
    //Main group
    System.out.println("Main Thread group: "+Thread.currentThread().getThreadGroup().getName());
    //System group  is the parent of main group. it contains system level threads like finalizer,signal dispatcher,attach listener
    System.out.println("Main Thread group: "+Thread.currentThread().getThreadGroup().getParent());
}

public void inturreptWork(){
    Inturrept inturrept= new Inturrept();
    Thread t1 = new Thread(inturrept,"Thread 1");
    Thread t2 = new Thread(inturrept,"Thread 2");
    Thread t3 = new Thread(inturrept,"Thread 3");
    try{
    t1.start();
    Thread.sleep(1000);
    t2.start();
    Thread.sleep(1000);
    t2.interrupt();
    t3.start();
    t1.join();
    t2.join();
    t3.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    finally {
        System.out.println("Finally");
    }


}

这里是 Inturrept 类

        public class Inturrept implements Runnable {
    Lock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            System.out.println("Trying to get lock ,Thread name is: " + Thread.currentThread().getName());
            lock.lock();// or   lock.lockInterruptibly();

            System.out.println("Running");
            Thread.sleep(7000);// Use something else to mimic sleep as it throws interrupted exception 
            lock.unlock();// This caused IllegalMonitorStateException 
        } catch (InterruptedException e) {
            System.out.println("I was inturrepted, Thread name is: " + Thread.currentThread().getName());
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

控制台输出:

Trying to get lock ,Thread name is: Thread 1
Running
Trying to get lock ,Thread name is: Thread 2
Trying to get lock ,Thread name is: Thread 3
Running
Exception in thread "Thread 1" I was inturrepted, Thread name is: Thread 2
java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    at com.test.main.Inturrept.run(Inturrept.java:21)
    at java.lang.Thread.run(Thread.java:748)
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.test.main.Inturrept.run(Inturrept.java:15)
    at java.lang.Thread.run(Thread.java:748)
Running
Exception in thread "Thread 3" Finallyjava.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    at com.test.main.Inturrept.run(Inturrept.java:21)
    at java.lang.Thread.run(Thread.java:748)

Main Thread group: main
Main Thread group: java.lang.ThreadGroup[name=system,maxpri=10]

正如答案中提到的“这与常规 lock() 相同。但是如果另一个线程中断等待线程 lockInterruptibly() 将抛出 InterruptedException。” 即使是 lock.lock() 或 lock.lockinterruptibly()。线程被中断。那么有什么区别呢?我是不是理解错了,请帮忙。 我还有一个问题是为什么我在控制台中看到“线程“线程 3”中的异常。它运行时我可以在日志中看到两个“运行”。

谢谢。

【问题讨论】:

  • 抛出 InterruptedException 的是 sleep,而不是 lock。当您 interrupt Thread 时,它会设置其 interrupted 标志并将其留在那里。当您的线程最终获得锁时,它处于这种中断状态并尝试sleep。 sleep 抛出 InterruptedException 如果任何线程中断了当前线程。
  • 另外,请将lock() 调用移到try 之外,并删除try 块内的unlock()。
  • @SotiriosDelimanolis 我在 try 中使用了 lock 方法,因为我也在使用 lockInterruptibly。是的,我在 try 中删除了解锁,我的错误是给出了 IllegalMonitorStateException 异常。使用 thread.sleep() 检查 lockInterruptibly 是否真的抛出中断异常也是错误的。因为当我中断线程时,它将中断标志设置为 true 使睡眠唤醒清除标志并发送抛出中断的异常。结果我无法确定 lockInterruptibly 是否真的抛出了 InterruptedException。如果有人过来
  • long now = System.currentTimeMillis();日期 d= new Date(Calendar.getInstance().getTimeInMillis()+5000);而(现在

标签: java multithreading concurrency java.util.concurrent


【解决方案1】:

lockInterruptibly() 首先检查线程是否被中断,如果被中断则抛出InterruptedException

 if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);

lock.unlock() 在你的代码中调用了两次。所以它抛出 IllegalMonitorStateException 因为不是同一个线程正在解锁。当线程在没有锁定的情况下进行解锁时,它会抛出异常。

 if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();

Thread.sleep 导致中断异常。Sleep 方法 throw InterruptedException

void sleep(long millis) throws InterruptedException

修改后的代码

 public void run() {
try {
    System.out.println("Trying to get lock ,Thread name is: " + Thread.currentThread().getName());
    lock.lock();
    System.out.println("Running");
    //Thread.sleep(7000);

} catch (Exception e) {
    System.out.println("I was inturrepted, Thread name is: " + Thread.currentThread().getName());
    e.printStackTrace();
} finally {
    lock.unlock();
}

}

【讨论】:

  • @SotiriosDelimanolis 我已经修改了我的答案。请您删除否决票
  • 感谢@gati 的回复,我想我应该使用 thread.sleep 以外的其他东西来模拟等待。
  • @Kid101 如果你喜欢我的帖子,请点赞,这样会有所帮助
猜你喜欢
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
相关资源
最近更新 更多