简体   繁体   中英

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

I'm seeing some multithreading issues when running safe1 method here:

    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.

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. 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. 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.

If the Test class is loaded by two different classloaders, then you will have two separate copies of the Test class. Whether Test.class is unique across the application depends on how the application is using classloaders. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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