【问题标题】:Java Multithread Access Static VariableJava 多线程访问静态变量
【发布时间】:2013-08-31 11:45:05
【问题描述】:

如何同时从多个线程访问静态变量。

如果我有类似的课程

Class A {
    public static boolean FLG=false;
    .....................
    ....................
}

我需要像访问线程 1 中的值

....................
public void run() {
    boolean t1=A.FLG;
    ..................
}

从线程 2 开始,我需要设置类似的值

....................
public void run() {
    A.FLG=true;
    ..................
}

这会导致内存冲突吗?如果是这样,处理这种情况的推荐方法是什么?

【问题讨论】:

    标签: java multithreading static


    【解决方案1】:

    如果你不想使用同步,ReentrantLock, 您可以为此编写自己的逻辑。

    例子:

    public class A extends Thread{
    
        public static boolean FLG=false;
    
        public A(String threadName) {
            start();
            setName(threadName);
        }
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true){
                if(this.getName().equals("getterThread") && FLG == true){
                    boolean t1=A.FLG;
                }
                if(this.getName().equals("setterThread") && FLG == false){
                    A.FLG = true;
                }
            }
    
        }
    
        public static void main(String[] args) {
    
            A dad = new A("getterThread");
            A son = new A("setterThread");
        }
    }
    

    【讨论】:

      【解决方案2】:

      在 Class A 中,您可以为 FLG 创建一个 set 和 get 方法,例如:

      public static synchronized boolean getFlag()
      {
      return FLG;
      }
      
      public static synchronized setFlag(boolean flag)
      {
      FLG=flag;
      }
      

      现在从其他线程,使用此方法访问FLG 的值。这将使FLG 的值在多个线程中保持一致。

      【讨论】:

      • 设置FLG怎么样,我可以照着做吗
      【解决方案3】:

      将静态变量封装在一个同步方法中,并随心所欲地调用该方法

      public static synchronized void method1(){
      //Whatever
      }
      
      public static synchronized void method2(){
      //Whatever again
      }
      

      请注意,还有其他方法可以同步对方法的访问。在繁忙的线程访问相同方法的环境中,它们被认为更有效。

      检查ReentrantLock 类。还有when to use synchronized and RentrantLock 的答案以及更多可以通过谷歌找到的信息。

      正如peter 的回答和muel 的评论所暗示的那样。将 boolean 变量标记为 volatile 应该会有所帮助。 volatile 布尔变量将缓存它的初始值(falsetrue)。 JVM 偶尔会这样做,这可能出乎程序员的意料。

      【讨论】:

      • 为什么不直接使用 volatile?
      • 如果变量的使用与代码示例中的完全一样。该领域甚至可以完全不受保护。线程 2 将设置它的值,线程 1 最终将看到该更改。如果可以接受读取陈旧值,则可以省略 volatile,因为对布尔值的写入在 32 位平台上是原子的。
      • 您指的是哪个代码示例? Thread 2...that change:什么意思?
      【解决方案4】:

      您可能会遇到一些不希望的情况,即两个线程尝试将不同的值设置到静态变量中,而您将无法确定究竟是什么值。最好的方法(在一个简单的场景中思考)我认为它是使用 AtomicBoolean (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html)并且你在对象中获取值并使用它(而不是一直使用对象,因为不同的线程可以改变它并且您可能会遇到意想不到的情况)。

      另一个建议是使用 Byteman 创建并发测试。

      问候, 栾

      【讨论】:

        【解决方案5】:

        如果您只想获取并设置一个原语,您可以将其设为volatile,并且对于这些操作来说它将是线程安全的。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 2012-06-11
        相关资源
        最近更新 更多