首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

java线程interrupte()方法中 重新获取锁 疑问求解!解决办法

2011-12-28 
java线程interrupte()方法中 重新获取锁 疑问求解!最近看到java多线程,《java多线程设计模式详解》书中提到:

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,两个线程互相隔离。


[解决办法]

探讨
楼上所说的对书上的做了部分改进,就是在没有获取锁的时候,a1程序状态被标记为isInterrupted,但a1线程无法抛出异常。

可是,程序在运行时,a2线程一直占有对象的锁,按道理a1无法获取锁,但是程序运行结果显示,a1抛出异常并被捕获,说明抛出异常前的锁不是a2占有的锁,或者我的程序有问题?

我就是想弄清楚,到底这个锁指的是哪个锁?程序有问题吗?


……

[解决办法]
书上说的并不是模糊,而是根本就是错误的:
“调用interrupt()方法时,会先重新获取锁定,在抛出InterruptedException异常”
这句话表明wait的线程重新获取锁定是因为调用了interrupt方法。这是错误的。

“调用interrupt()方法时会重新获得锁定”,是否重新获得锁定与是否调用interrupt()没有任何关系,那是系统调度的事情。正确的表述就是:
“调用interrupt()方法后,如果重新获取锁定,就会抛出InterruptedException异常”。
[解决办法]
调用interrupt()方法时会提示中断,重新获得锁,虽然不是立刻执行,但是你不这样,会永远堵塞下去,这说明interrupt()在某种情况下能起作用。
[解决办法]
说明你还是不懂。

热点排行