简体   繁体   English

静态同步方法和非同步静态方法混淆

[英]Static synchronized methods and non-synchronized static methods confusion

I have a small confusion. 我有一点困惑。 Please have a look at the code below. 请看下面的代码。

public class ThreadDemo {
  //non-static synchronized method
  synchronized void a(){
   actBusy();
  }

  //static synchronized method
  static synchronized void b(){
    actBusy();
  }

  //static method
  static void actBusy(){
    try{
      Thread.sleep(1000);
    }
    catch(InterruptedException e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args){
    final ThreadDemo x = new ThreadDemo();
    final ThreadDemo y = new ThreadDemo();
    Runnable runnable = new Runnable() {
      public void run() {
         int option = (int) (Math.random() * 4);
         switch (option){
           case 0: x.a();
             break;
           case 1: x.b();
             break;
           case 2: y.b();
             break;
           case 3: y.b();
             break;
         }
      }
    }   ;
    Thread t1 = new Thread(runnable);
    Thread t2 = new Thread(runnable);
    t1.start();
    t2.start();
  }
}

I know for sure that invocation of this sequence is possible. 我确信可以调用这个序列。

x.a() //in Thread-1
y.b() //in Thread-2

Though still I have a small confusion that, we can easily see xa() also calls actBusy() method which is a static method. 虽然我仍然有一点混乱,但我们可以很容易地看到xa()也调用actBusy()方法,这是一种静态方法。 Method b() is a static synchronized method calling a non-synchronized static method. 方法b()是一个调用非同步静态方法的静态同步方法。 When thread-2 gets a class level lock, the why call of actBusy() from Thread-1 is not blocked? 当thread-2获得类级别锁定时,为什么不阻止来自Thread-1的actBusy()调用?

I am just logically confused, if a thread gets a class level lock, that class other non-synchronized static methods remain open to be called from other methods (instance method). 我只是在逻辑上混淆,如果一个线程获得类级别锁定,该类其他非同步静态方法保持打开以从其他方法(实例方法)调用。 Why? 为什么?

then why call of actBusy() from Thread-1 is not blocked? 为什么不阻止从Thread-1调用actBusy()

Since your actBusy method is NOT synchronized. 由于您的actBusy方法未同步。 Even if you acquired class level lock you can invoke non-synchronzied static methods. 即使您获得了类级别锁定,也可以调用非同步静态方法。

The point of marking the methods as synchronized is to enable locks. 将方法标记为已synchronized是启用锁定。 Only methods declared as synchronized are subjects to these locks. 只有声明为synchronized的方法才是这些锁的主题。 So if you acquired a lock (suppose class level lock) then any non-synchronized method acts as before and isn't aware of lock being acquired. 因此,如果您获得了一个锁(假设类级别锁定),则任何non-synchronized方法都会像以前一样起作用,并且不知道正在获取锁定。 This allows you to decide which methods need to be blocked and which don't. 这允许您决定哪些方法需要阻止,哪些方法不需要。

static synchronized method has a lock on the class object , while non static synchronized method has a lock on the instance object ( this ) - so both methods can be invoked concurrently, and one thread will run 1 while the other run the 2nd. static synchronized方法对类对象有一个锁,而非静态synchronized方法对实例对象有一个锁( this ) - 所以两个方法可以同时调用,一个线程运行1而另一个运行第二个。

However, note that there is no race condition available in your code, because race condition requires a write, and such does not exist in these methods. 但请注意,您的代码中没有可用的竞争条件 ,因为竞争条件需要写入,这些方法中不存在这种情况。

actBusy() is itself not synchronized but the callers methods are. actBusy()本身不是同步的,但调用方法是。

So Thread 1 does not block as it acquires lock on this object and no other thread holds lock on this , so it is able to call it without any problem. 因此,线程1不会阻塞,因为它获取this对象的锁定,并且没有其他线程this持有锁定,因此它可以毫无问题地调用它。

That is because the non-static synchronized method locks on this the present instance and not on class object. 这是因为non-static synchronized上方法锁this本实例而不是class对象。

xa() grabs a lock on the present instance ie x and no other thread will be able to enter method a() of x until the present the present thread releases the lock. xa()获取当前实例的锁,即x并且没有其他线程能够输入x方法a() ,直到当前线程释放锁。

Thread 1 --> xa() //acquires lock and holds it 线程1 - > xa() //acquires lock and holds it

Thread 2 ---> xa() //blocks here until Thread 1 releases lock on x 线程2 ---> xa() //blocks here until Thread 1 releases lock on x

EDIT: 编辑:

Class Object != Instance 

So according to JMM they are different objects and two threads don't interfere with each other. 因此根据JMM,它们是不同的对象,并且两个线程不会相互干扰。 So it allows you to call it. 所以它允许你调用它。

EDIT 2: 编辑2:

why does it allow calls to other static methods? 为什么它允许调用其他静态方法? Any logic behind it? 它背后的任何逻辑?

Suppose this: 假设这个:

public static synchronized int statefulMethod(){
    //this should be protected
}

public static int nonStatefulMethod(){
    //Just returns a static value such as 5
    //so this is thread safe as it does not have any state
}

public static synchronized int otherStatefulMethod(){
    //this should also be thread safe
}

So if thread 1 is in method statefulMethod() which is having some shared state to protect so it uses class level lock. 因此,如果线程1在方法statefulMethod()中有一些共享状态要保护,那么它使用类级别锁定。 Now thread 2 calls nonStatefulMethod() then it should not logically block as that method is thread safe and there is no point in making that thread block here . 现在线程2调用nonStatefulMethod()然后它不应该逻辑阻塞,因为该方法是线程安全的,并且没有必要在此处进行该线程阻塞

Now if thread 3 calls the otherStatefulMethod() while thread 1 is holding class lock then thread 3 will have to wait as that method is also static-synchornized . 现在,如果线程3调用otherStatefulMethod()而线程1持有类锁,那么线程3必须等待,因为该方法也是static-synchornized

Lock objects are not hierarchical. 锁定对象不是分层的。 Therefore obtaining a lock on the class itself does not supersede locks on instances of your class. 因此,获取类本身的锁定并不会取代对类实例的锁定。 They are separate lock objects and will only block code that attempts to lock on exactly that same object. 它们是单独的锁定对象,只会阻止尝试锁定同一对象的代码。

So if a thread enters a static synchronized method, the only threads that will be blocked are those also trying to enter a static synchronized method on the same class. 因此,如果一个线程进入静态同步方法,那么唯一将被阻塞的线程也是那些试图在同一个类上输入静态同步方法的线程。 Threads that are merely trying to enter an non-static synchronized method are unaffected - they are only competing against threads trying to enter non-static synchronized methods on that same object instance. 仅仅尝试进入非静态同步方法的线程不受影响 - 它们仅与试图在同一对象实例上输入非静态同步方法的线程竞争。

Regarding your comment below - only static methods marked synchronized are subject to the class level lock. 关于下面的注释 - 只有标记为synchronized静态方法才会受到类级锁定的影响。 If you want other static methods to be blocked, you must also mark them synchronized . 如果要阻止其他静态方法,还必须将它们标记为已synchronized

Why is this the case? 为什么会这样? Well, it would be rather presumptuous for the compiler to assume you need to lock all your static methods simply because one is marked as synchronized . 好吧,编译器假设您需要锁定所有静态方法只是因为一个被标记为已synchronized ,这是相当冒昧的。 It is assumed that the programmer knows which methods must be synchronized in order to ensure thread safety. 假设程序员知道必须同步哪些方法以确保线程安全。

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

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