Java多线程访问静态变量

4

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

如果我有一个类像这样

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

我需要像以下这样从线程1中访问该值:

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

我需要将值从线程2设置为:

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

这会导致内存违规吗?如果是的话,应该如何处理这种情况?

5个回答

5

如果你只是想获取和设置一个原始类型,你可以将它设置为volatile,这样它就能保证在多线程下进行这些操作时是安全的。


我需要访问值并设置值。 - Haris
嗯,有趣。我认为"Java中的volatile关键字文档不完善,理解不足,且很少使用"是正确的。 无论如何,看起来volatile并不完全等同于将访问器设置为synchronized - Jonik

4

将静态变量包装在同步方法中,随意调用该方法。

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

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

请注意,同步访问方法还有其他方法。在繁忙的线程访问相同方法的环境中,它们被认为更有效率。
请查看ReentrantLock类。还有何时使用synchronized和RentrantLock等答案以及通过Google可以找到的更多信息。
另外,正如peter的回答和muel的评论所建议的那样,将boolean变量标记为volatile应该是有帮助的。volatile布尔变量不会缓存其初始值(falsetrue)。JVM偶尔会这样做,这可能出乎程序员的意料之外。

2
为什么不直接使用volatile? - Muel
如果变量在代码示例中被完全按照其使用方式使用,该字段甚至可以完全不受保护。线程2将设置其值,线程1最终将看到该更改。如果可以接受读取过时的值,则可以省略“volatile”,因为在32位平台上,对布尔值的写入是原子的。 - Giulio Franco
你指的是哪个代码示例? Thread 2...that change: 你是什么意思? - Muhammad Gelbana

1
在A类中,您可以创建一个用于FLG的set和get方法,例如:
public static synchronized boolean getFlag()
{
return FLG;
}

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

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

关于设置FLG,我可以遵循相同的方法吗? - Haris

1
你可能会遇到一些不希望出现的情况,其中两个线程尝试将不同的值设置为静态变量,并且你无法确定真正存在的值是什么。我认为最好的方法(在一个简单的场景中考虑)是使用AtomicBoolean( http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html )来获取对象中的值并使用它(而不是始终使用对象,由于不同的线程可以改变它,因此您可能会得到意外的情况)。
另一个建议是使用Byteman创建并发测试。
问候, Luan

0

如果您不想使用synchronized,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");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接