简体   繁体   English

锁定 static 最终 object 属性与基于 class 类型的锁定代码

[英]Locking on static final object attribute vs locking code based on class type

I'm seeing some multithreading issues when running safe1 method here:我在这里运行 safe1 方法时看到了一些多线程问题:

    public class Test {

    private static final Object lock = new Object();

    public void safe1() {
        //Some non thread safe code
        synchronized (lock) {
            //Some thread safe code
        }
        //Some non thread safe code.
    }
    
    public void safe2() {
        //Some non thread safe code
        synchronized (lock) {
            //Some thread safe code
        }
        //Some non thread safe code.
    }
}

I was thinking it has the same behavior than this code.我在想它的行为与这段代码相同。

public class Test {

    public void safe1() {
        //Some non thread safe code
        synchronized (Test.class) {
            //Some thread safe code
        }
        //Some non thread safe code.
    }
    
    public void safe2() {
        //Some non thread safe code
        synchronized (Test.class) {
            //Some thread safe code
        }
        //Some non thread safe code.
    }
}

Is that correct?那是对的吗? I want to ensure no 2 threads are running the same "safe code", VM wide.我想确保没有 2 个线程在 VM 范围内运行相同的“安全代码”。

The difference is somebody could write code acquiring a lock like不同之处在于有人可以编写获取锁的代码,例如

synchronized(Test.class) {

and be able to acquire the lock without calling the methods on a Test object.并且能够在不调用测试 object 上的方法的情况下获取锁。 Any arbitrary code in the application could acquire the lock and possibly prevent your other code using it from progressing.应用程序中的任何任意代码都可以获取锁,并可能阻止使用它的其他代码继续进行。 Locking on a private field makes that harder, the code would have to get the private field with reflection and the security manager could be configured to prevent that.锁定私有字段会使事情变得更加困难,代码必须通过反射来获取私有字段,并且可以配置安全管理器来防止这种情况发生。

Otherwise the scoping of the lock is the same, you're letting in one thread at a time across all instances of the Test class for the whole classloader.否则,锁的作用域是相同的,您一次允许一个线程跨越整个类加载器的 Test class 的所有实例。 So creating more Test instances doesn't help your concurrency level.所以创建更多的测试实例对你的并发水平没有帮助。 If you are protecting instance data then that would seem unnecessarily constricting.如果您正在保护实例数据,那么这似乎是不必要的限制。 The locking scope should be the same as the scope of the data you're preventing concurrent access to.锁定 scope 应该与您阻止并发访问的数据的 scope 相同。

If the Test class is loaded by two different classloaders, then you will have two separate copies of the Test class.如果测试 class 由两个不同的类加载器加载,那么您将拥有测试 class 的两个单独副本。 Whether Test.class is unique across the application depends on how the application is using classloaders. Test.class 在整个应用程序中是否唯一取决于应用程序如何使用类加载器。 But neither of your approaches is preferable with respect to that.但是就这一点而言,您的任何一种方法都不是可取的。

This code will not allow to any other thread to take access in the same class loader of the jvm.此代码不允许任何其他线程访问 jvm 的同一 class 加载程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM