日期:2014-05-20  浏览次数:20712 次

java线程interrupte()方法中 重新获取锁 疑问求解!
最近看到java多线程,《java多线程设计模式详解》书中提到:“线程在进入等待区时,会把锁定解除。当对wait中的线程(即等待被取消的线程)调用interrupt()方法时,会先重新获取锁定,在抛出InterruptedException异常,在获取锁定之前,并无法抛出InterruptedException异常”。

  我的理解是:如果无法获取锁定,则即使调用interrupte方法也不会抛出异常,现在我疑问的是这个锁是什么锁??
好像不是调用wait()的锁,因为我写了3个类做了简单的测试,发现不获取锁定一样能够抛出异常

  希望各位多线程高手能指点指点

A类:
public class A extends Thread{
private final Object o = new Object();
private static boolean test = true;
public A(String name)
{
super(name);
}
public void run()
{

System.out.println(Thread.currentThread().getName()+"开始运行");
int i = 0;
synchronized(o) {
try {
  //死循环
while(true){
if(test)  
  //test为静态变量,改变后其他实例线程就不会进入wait()状态
  //保证第二个线程不会进入wait状态,第二个线程在死循环中一直占有锁
{
test = false;
System.out.println(Thread.currentThread().getName()+"开始进入等待");
o.wait();


}
System.out.println(Thread.currentThread().getName()+"正在运行,次数:"+i);

Thread.sleep(1000);
i++;
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"退出");
}

}
}
}


B类:
public class B extends Thread{
private Thread t ;
public B(Thread t)
{
this.t = t;
}
public void run(){
try {
System.out.println("线程B开始运行");
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开始取消线程");
t.interrupt();//调用一个线程的中断方法
System.out.println("线程取消方法被调用,B退出");
}
}

测试主类:
public class TestMain {
public static void main(String[] args) {
A a1 = new A("a1");
A a2 = new A("a2");
B b = new B(a1);
a1.start();
a2.start();//a1会进入wait()方法,a2则一直运行
b.start();
}
}



在线程b中调用a1线程的中断interrupt方法后,a1线程抛出异常被捕获,然后a1线程退出


------解决方案--------------------
如果书上真是那么描述的,只能说明作者根本不懂。

“线程在进入等待区时,会把锁定解除。当对wait中的线程(即等待被取消的线程)调用interrupt()方法时,会先重新获取锁定,在抛出InterruptedException异常,在获取锁定之前,并无法抛出InterruptedException异常”
正确的描述是:
“线程在进入等待区时,会把锁定解除。当对wait中的线程(即等待被取消的线程)调用interrupt()方法后,如果线程重新获取了锁定,会抛出InterruptedException异常,在获取锁定之前,并无法抛出InterruptedException异常”

如果线程a进入wait,它释放了锁,这时其它线程(不一定是获取了锁的那个线程,有可能就不和他们产生锁竞争的线程)调用了a的interrupt()方法,没有任何反映,只是改变了a的可执行状态,如果没有调用,当a有机会获取到锁时,就会检查是否达到wait的时间,如果没有达到就继续wait,达到了就恢复执行,而如果a被调用了interrupt()方法的瞬间,因为只是状态被修改为已经被中断(isInterrupted),如果它有机会获取到锁,才会抛出异常。而如果其它线程一直抓住锁没有释放,那么它当然不会抛出异常(没有难给它发言的机会啊,只是它的内部状态被标记为isInterrupted而已)。
------解决方案--------------------
现在我疑问的是这个锁是什么锁??
---
就是指你调用.wait那个对象锁,即
synchronized(o)这个

你把代码这样写

Java code

        final Object o = new Object();
        Thread t = 
        new Thread() {
            public void run() {
                synchronized (o) {
                    try {
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("After Wait");
                }
            }
        };
        t.start();
        Thread.sleep(2000);
        synchronized (o) {
            t.interrupt();
            System.out.println("After Interrupt");
            Thread.sleep(5000);
            System.out.println("After Sleep");
        }

------解决方案--------------------
a1线程有有机会获得锁定,但是没有通过o.notify()通知,如果别的线程调用t.interrupt(),会促使a线程去重新获得锁定,这是就会抛出异常,书上说的没错,只是比较模糊而已。
------解决方案--------------------
a1线程跟a2线程在对象锁方面没有关系。对象o,两个线程互相隔离。