Java static / non-static synchronized方法同时修改static成员变量,会有问题吗?

发布于 2022-09-04 10:50:57 字数 916 浏览 16 评论 0

Java里staticnon-static synchronized方法锁住的分别是对象,因而是可以同时执行的,那么会存在修改问题吗?搜索没有得到比较关联的答案,来这里问问大家:

示例代码如下:

public class Test {
    
    private static int staticVariableOne = 0;
    
    public synchronized void nonStaticFunction() {
        // do some works
        staticVariableOne++;
        // do some works
    }
 
    public synchronized static void staticFunction() {
        // do some works
        staticVariableOne++;
        // do some works
    }

}

以上,两个线程分别同时调用nonStaticFunction()和staticFunction(),会出现这种情况(导致一次修改丢失)吗:

1. nonStaticFunction 读 staticVariableOne = 0
2. nonStaticFunction 阻塞
3. staticFunction 读 staticVariableOne = 0
4. staticFunction 写 staticVariableOne = 1
5. nonStaticFunction 继续
6. staticFunction 写 staticVariableOne = 1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

睫毛上残留的泪 2022-09-11 10:50:57

参考StackOverflow问题:

http://stackoverflow.com/ques...

但是,还是意犹未尽,还请各位多多指教、探讨!


补充:

运行如下测试程序,最后的结果并不是20000,中间有很多次结果都被覆盖了。

public class Test {
    
    private static int staticVariableOne = 0;

    public Test() {
        super();
    }
    
    public static int getStaticVariableOne() {
        return staticVariableOne;
    }

    public static void setStaticVariableOne(int staticVariableOne) {
        Test.staticVariableOne = staticVariableOne;
    }
    
    private static void increaseStaticVariableOne() {
        staticVariableOne++;
    }
    
    public synchronized void add() {
        System.out.println("执行 add() 开始...");
        try {
            for (int i  = 0; i < 10000; i++) {
                increaseStaticVariableOne();
                Thread.sleep(1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行 add() 完毕...");
    }
 
    public synchronized static void addStatic() {
        System.out.println("执行 addStatic() 开始...");
        try {
            for (int i  = 0; i < 10000; i++) {
                increaseStaticVariableOne();
                Thread.sleep(2);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行 addStatic() 完毕...");
    }

}
public class StudyMain {
    public static void main( String[] args ) {
        
        final Test insertData = new Test();
        Thread threadOne = new Thread() {
            @Override
            public void run() {
                insertData.add();
            }
        };
        
        Thread threadTwo = new Thread() {
            @Override
            public void run() {
                Test.addStatic();
            }
        };
        
        threadOne.start();
        threadTwo.start();
        try {
            threadOne.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            threadTwo.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("After 20000 times increasements, final staticVariableOne is "
        + Test.getStaticVariableOne());
    }
}
无所的.畏惧 2022-09-11 10:50:57

不清楚你的困惑在哪里……staticnon-static synchronized方法锁住的分别是对象类的实例,锁的作用对象都不同。你分别通过threadOne调用add()方法,threadTwo调用addStatic()方法,两个线程同时对一个线程不安全的共享变量进行值的修改,肯定要注意并发问题。要解决你的问题的话,有两个方案:
(1)定义一个私有构造函数,禁止类被实例化,让所有的操作都通过Test.addStatic()方法去执行;
(2)使用线程安全的方式来申明变量staticVariableOne

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文