函数内的多线程变量访问

时间:2009-12-24 14:11:16

标签: java variables multithreading

我有一个启动几个线程的函数(它是一个测试函数),其中一个线程会改变变量的状态。由于局部变量不能标记为volatile,我假设该方法中的多个线程将始终具有变量的更新状​​态。它是否正确?这是示例代码

public void someMethod() {
   MutableBoolean mb = new MutableBoolean(false);
   Thread t1 = new Thread() {
       public void run() {
           while (someCondition) {
              if ( mb.getValue() ) {
                 ...do something
              }
           }
       }  
   }
   t1.start();

   Thread t2 = new Thread() {
         public void run() {
             if ( someCondition ) {
                mb.setValue(true);
             }
         }
   }
   t2.start();  

   ...wait for the threads to complete

}

4 个答案:

答案 0 :(得分:6)

除非MutableBoolean在其set / get值方法中使用锁,否则它是一个原子操作,那么这不是线程安全的。

getValue可能正在读取值,而setValue正在更新它。你可以用布尔值来解决这个问题,但对于任何更复杂的类型,它可能会失败。

锁定对共享状态的访问以使其线程安全。

答案 1 :(得分:0)

要获得线程间可见性, volatile不是唯一的选择。任何同步(锁定)也可以。

在这种情况下,MutableBoolean可以是一个线程安全的类,这样就可以完成这项工作。


正如danben所说,MutableBoolean可能需要final传递给函数。

您是否在发布之前在IDE中测试了代码?

答案 2 :(得分:0)

mb必须定义为final,否则代码将无法编译(匿名类只能访问声明范围的最终变量)。最终变量不能改变其值,因此从技术上讲,t1和t2总是会在mb处看到相同的值。出于这个原因,mb易失性的问题是无关紧要的。

你的问题不是关于mb对象本身的状态(MutableBoolean对象的字段所持有的值)。对于这些字段,您可以使用volatile和/或synchronized方法来确保线程安全。

答案 3 :(得分:0)

以前的海报是正确的,如果不使 mb 最终,这段代码将无法编译。对于引用类型,final意味着您无法更改变量引用的对象。 意味着您无法更改该对象的状态。因此,您不能使 mb 引用 MutableBoolean 的不同实例,但 setValue(...)将一如既往地运行。应该同步 MutableBoolean.getValue() MutableBoolean.setValue(...),以便一个线程可以看到彼此的变化。

请注意,无法保证两个新线程中的语句将以何种顺序运行。或者t2或t1可能先运行,或者指令可能是交错的。

mb 是一个局部变量这一事实确实影响了这一点,但要求它是最终的。

有关此主题的明确字词,请参阅Java Concurrency in Practice

相关问题