3

我有一本我正在学习的 Java 书,在其中一个示例中,我看到了一些可疑的东西。

public class ThreadExample extends MIDlet {
    boolean threadsRunning = true; // Flag stopping the threads

    ThreadTest thr1;
    ThreadTest thr2;

    private class ThreadTest extends Thread {
        int loops;

        public ThreadTest(int waitingTime) {
            loops = waitTime;
        }

        public void run() {
            for (int i = 1; i <= loops; i++) {
                if (threadsRunning != true) { // here threadsRunning is tested
                    return;
                }

                try {
                    Thread.sleep(1000);
                } catch(InterruptedException e) {
                    System.out.println(e);
                }
            }
        }
    }

    public ThreadExample() {
        thr1 = new ThreadTest(2);
        thr2 = new ThreadTest(6);
    }

    public void startApp() throws MIDletStateChangeException {
        thr1.start();
        thr2.start();

        try {
            Thread.sleep(4000); // we wait 4 secs before stopping the threads - 
                                // this way one of the threads is supposed to finish by itself
        } catch(InterruptedException e) {
            System.out.println(e);
        }

        destroyApp();
    }

    public void destroyApp() {    
        threadsRunning = false;

        try {
            thr1.join();
            thr2.join();
        } catch(InterruptedException e) {
            System.out.println(e);
        }

        notifyDestroyed();
    }
}

由于它是一个 MIDlet 应用程序,当它启动时,会执行 startApp 方法。为了简单起见,startApp 方法本身调用destroyApp,因此程序销毁,停止线程并通知销毁。

问题是,使用这个“threadsRunning”变量是否安全,它在两个线程和destroyApp方法中的使用是否会在某些时候造成任何麻烦?将'volatile'关键字放在声明前面有助于同步它吗?

4

1 回答 1

6

设置一个布尔值是原子的,在这个例子中没有“读取然后修改”的逻辑,所以在这种特殊情况下对变量的访问不需要同步。

但是,该变量至少应标记为 volatile。

标记变量 volatile 不会同步线程对其的访问;它确保一个线程不会因为代码优化或值缓存而错过另一个线程对变量的更新。例如,如果没有volatile,里面的代码run()可能会在开始时只读取threadsRunning一次值,缓存该值,然后if每次在语句中使用这个缓存的值,而不是再次从主存中读取变量。如果该threadsRunning值被另一个线程更改,它可能不会被拾取。

一般来说,如果你使用来自多个线程的变量,并且它的访问是不同步的,你应该将它标记为 volatile。

于 2011-11-09T10:24:50.463 回答