如果某个线程使对象为null而其他线程在该对象的方法内,则会发生什么

时间:2012-12-16 13:32:55

标签: java multithreading garbage-collection

假设我有 -

public class ThreadingIssue {
    public B b = new B();
}

class B{
    private final Object lock = new Object();

    public void someMethod(int timeOut){
        synchronized(lock){
            try{
                lock.wait(timeOut);
            }catch(Exception e){
            }
            // some task..
            lock.notifyAll();
        }
    }
}

class Thread1 implements Runnable{
    private ThreadingIssue t;

    public Thread1(ThreadingIssue issue) {
        t = issue;
    }

    public void run(){
        while(true){
              t.b.someMethod(5000);
        }
    }
}

class Thread2 implements Runnable{
    private ThreadingIssue t;

    public Thread2(ThreadingIssue issue){
        t = issue;
    }

    public void run(){
        try{
            Thread.sleep(2000);
        }catch(Exception e){
        }
        t.b = null;
    }
}

Thread1会发生什么,如果它在B的someMethod(5000)内并等待锁定,并且Thread2使B的对象为空?我不确定Thread1是否会抛出哪个异常..任何帮助?

2 个答案:

答案 0 :(得分:3)

第二个线程保存对正在运行其方法的对象的引用(否则它将无法运行其实例方法),因此GC无法处置该对象,因此不存在异常。

在您执行

时更明确地使用您的代码
t.b.someMethod(5000)

JVM内部处理t.b表达式(对象的引用),因此引用计数不为0.

答案 1 :(得分:1)

总结SJuan76和op的讨论:
看起来有两个对t的引用,但只有一个对b(t中的一个)。 t不会被释放,因为线程独立地保持它。但是,b可能会被删除(取决于gc),因为一旦引用无效,其引用计数将降至零 所以Thread2可能会抛出NullPointerException。

编辑:
在someMethod()中,b对象不会被释放,因为this指针保持在堆栈上,至少使ref计数为1。每次执行成员方法都可以说同样的事情,因为每个成员方法都会以this作为参数。

请注意,虽然您获得了NullPointerException,但这并不意味着对象已经完成/释放,只是您正在使用的引用为null。 GC可能需要一些时间来实际释放对象。