我爱学Java之Thread中stop(),suspend(),resume()为什么不安全

来源:互联网 发布:高中化学大全软件下载 编辑:程序博客网 时间:2024/05/15 22:50

当调用stop()方法时会发生两件事:

1.即刻停止run()方法中剩余的全部工作,包括在catch或finally语句中,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。

2.会立即释放该线程所持有的所有的锁,导致数据得不到同步的处理,出现数据不一致的问题。

举个例子:

public class Main{    public static void main(String [] args) throws Exception{        TestObject testObject = new TestObject();        Thread t1 = new Thread(){            public void run(){                try {                    testObject.print("1", "2");                } catch (Exception e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        };        t1.start();        Thread.sleep(1000);        t1.stop();        System.out.println("first : " + testObject.getFirst() + " " + "second : " + testObject.getSecond());    }}class TestObject{    private String first = "ja";    private String second = "va";    public synchronized void print(String first, String second) throws Exception{        this.first = first;        Thread.sleep(10000);        this.second = second;    }    public String getFirst() {        return first;    }    public void setFirst(String first) {        this.first = first;    }    public String getSecond() {        return second;    }    public void setSecond(String second) {        this.second = second;    }}

输出:

first : 1 second : va

从上面的程序验证结果来看,stop()确实是不安全的。它的不安全主要是针对于第二点:释放该线程所持有的所有的锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放,那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。

suspend()和resume()必须要成对出现,否则非常容易发生死锁。
因为suspend方法并不会释放锁,如果使用suspend的目标线程对一个重要的系统资源持有锁,那么没任何线程可以使用这个资源直到要suspend的目标线程被resumed,如果一个线程在resume目标线程之前尝试持有这个重要的系统资源锁再去resume目标线程,这两条线程就相互死锁了,也就冻结线程。

举个例子:

public class Main{    public static void main(String [] args) throws Exception{        TestObject testObject = new TestObject();        Thread t1 = new Thread(){            public void run(){                testObject.print();            }        };        t1.setName("A");        t1.start();        Thread.sleep(1000);        Thread t2 = new Thread(){            public void run(){                System.out.println("B已启动,但进入不到print方法中");                testObject.print();            }        };        t2.setName("B");        t2.start();    }}class TestObject{    public synchronized void print(){        if(Thread.currentThread().getName().equals("A")){            System.out.println("A 线程 独占该资源了");            Thread.currentThread().suspend();        }    }}

输出:

A 线程 独占该资源了已启动,但进入不到print方法中
0 0
原创粉丝点击