4

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

如果我有一个像

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

我需要从线程 1 访问值,例如

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

从线程2我需要设置像

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

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

4

5 回答 5

5

If all you want to do is get and set a primitive you can make it volatile and it will be thread safe for those operations.

于 2013-08-28T12:05:47.887 回答
3

将静态变量包装在同步方法中,并根据需要调用该方法

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

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

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

检查ReentrantLock类。还有关于何时使用同步和 RentrantLock的答案以及可以通过 google 找到的更多信息。

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

于 2013-08-28T12:03:17.717 回答
1

In Class A , you can create a set and get method for FLG like:

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

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

Now from other Threads, access value of FLG usng this method. This will keep the value of FLG Consistent across multiple Threads.

于 2013-08-28T12:06:03.657 回答
1

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

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

问候, 栾

于 2013-08-28T12:09:41.583 回答
0

如果你不想使用同步,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");
    }
}
于 2013-08-28T12:39:40.073 回答