是否为线程更新了公共静态变量? (它是线程安全的吗?)

时间:2012-08-04 01:36:18

标签: java thread-safety

我尝试了以下操作并且无效:

“开始”课程:

public class Start implements Runnable {

    Start start;
    LoadExample loadExample;
    Thread mainThread;
    Thread loadExampleThread;

    private boolean running = false;
    public static boolean isExampleLoaded = false;

    public static void main(String[] args) {
        begin = new Start();
        loadExample = new LoadExample();
        begin.start();
    }

    public synchronized void start() {
        mainThread = new Thread(this, "Main");
        mainThread.start();
        loadExampleThread = new Thread(loadExample, "Load Example");
        loadExampleThread.start();
    }

    public void run() {
        running = true;
        while (running) {
            if(isExampleLoaded){
                System.out.println("Loaded!");
            }
        }
    }
}

“LoadExample”类:

public class LoadExample implements Runnable {

    public void run(){
        //blabla, loading if you will...
        Start.isExampleLoaded = true;
    }
}

您可能会在上面的代码中发现语法错误,但这只是因为我在没有签入Eclipse的情况下输入了这个错误。我的原始代码非常相似,Eclipse没有显示任何错误或警告。

我的问题是代码不会打印“已加载!”。 我认为这是因为(1)线程无法更改静态变量或其他类的变量,或者(2)更改只是更新当前线程而不是其他(s),但我可能错了。

任何澄清都表示赞赏。

修改

如果您发现上述任何错误,请告诉我,我会尽快更新。

2 个答案:

答案 0 :(得分:6)

您需要标记变量volatile才能使此示例正常工作。如果没有volatile,读取线程将读取isExampleLoaded一次,而不再读取它,因为编译器知道该变量尚未写入。

答案 1 :(得分:1)

每当您想要从多个线程访问变量时,所有对该变量的访问都应该在synchronized块或方法中,所有这些都使用相同的监视器。在本程序中,如果您制作了静态同步isExampleLoaded()setExampleLoaded()方法,并在任何地方使用这些方法,该程序将起作用。

正如@dasblinkenlight指出的那样,也可以将变量标记为volatile,这也可以。 volatile不能扩展到许多变量或许多线程。在一般情况下,synchronized访问权限是更好的解决方案。