4

说我有:

class WriteThread extends Thread {
    char letter;
    boolean stop = false; 
    WriteThread(char letter) {
        this.letter = letter;
    }
    public void halt() { stop = true; }
    public void run() {
        while(!stop) { System.out.print(letter); }
    }
}

和:

WriteThread a = new WriteThread('a');
WriteThread b = new WriteThread('b');
a.start(); 
b.start();
// do some other stuff
a.halt();
b.halt(); // (*)

执行 (*) 时是否保证两个线程都停止?(停止是指在 (*) 之后不再有打印)

4

3 回答 3

4

您需要使“停止”变量易变。当线程看到 vale 为真时,它会停止循环,但可能存在输出缓冲,这会混淆问题。

于 2013-02-26T00:48:23.140 回答
1

当然不是。它与volatile与否无关,它只是多线程的本质。

在你调用 a.halt() 之后,线程 a 可能没有机会继续执行,而你的主线程执行 b.halt()。在那之后,线程 a 可能仍然在您的 println 语句之前的位置。

只是一个简化版本将演示:

MAIN THREAD                THREAD A
                           while (!stop)
a.halt()
                           println(...)

调用后a.halt()a仍有机会继续打印,EVENstop变量是 volatile。

为了确保线程在某个点之后完成,请使用 join():

WriteThread a = new WriteThread('a');
WriteThread b = new WriteThread('b');
a.start(); 
b.start();
// do some other stuff
a.halt();
b.halt();
a.join();
b.join();
// a and b are guaranteed to have finished at this point
于 2013-02-26T01:58:19.220 回答
0

除了使“stop”变量易失之外,为了使您的代码更加“线程安全”,您应该为“stop”添加同步的 get/set 方法并使用它们(“get”在 while 循环中,“set”在“停止”方法)。

尽管如此,您无法保证线程会在“暂停”后停止,但您可能会看到更少的“打印”。

要获得这样的保证,您必须使用某种“线程同步”机制,例如Semaphore,以使调用“a.halt()”的线程向“a”线程发出信号以停止“while”循环并停止(内部停止),直到“while”循环有效结束并“释放”信号量(因此调用线程继续执行)。

于 2013-02-26T01:17:30.160 回答