当前位置: 首页 > 知识库问答 >
问题:

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

宗政元青
2023-03-14

我有点困惑。请看看下面的代码。

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();
  }
}

我确信调用此序列是可能的。

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

虽然我仍然有一个小小的困惑,但我们可以很容易地看到x.a()也调用actBusy()方法,这是一个静态方法。方法 b() 是调用非同步静态方法的静态同步方法。当 thread-2 获得类级锁时,为什么从 Thread-1 调用 actBusy() 没有被阻止?

我只是在逻辑上感到困惑,如果一个线程获得类级锁定,则该类其他非同步静态方法保持打开状态,以便从其他方法(实例方法)调用。为什么?

共有3个答案

华星文
2023-03-14

actBusy() 本身不是同步的,但调用方方法是同步的。

因此,线程1在获取< code>this对象上的锁时不会阻塞,并且没有其他线程持有< code>this上的锁,因此它能够毫无问题地调用它。

这是因为<code>非静态同步

x.a() 在当前实例(即 x)上抓取一个锁,在当前线程释放锁之前,没有其他线程能够输入 x 的方法 a()。

线程1 -

线程2 -

编辑:

Class Object != Instance 

所以根据JMM,它们是不同的对象,两个线程不会相互干扰。所以它允许您调用它。

编辑2:

为什么它允许调用其他静态方法?背后有什么逻辑吗?

假设:

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
}

因此,如果线程 1 处于方法 statefulMethod() 中,则它具有一些共享状态需要保护,因此它使用类级锁。现在线程2调用nonStatefulMethod(),那么它不应该在逻辑上阻塞,因为该方法是线程安全的,在这里创建该线程块是没有意义的。

现在,如果线程3在线程1持有类锁时调用therStatefulMethod(),那么线程3将不得不等待,因为该方法也是静态同步的

苏嘉志
2023-03-14

static synchronized方法在类对象上有一个锁,而非静态synchronizemethod在实例对象上有锁(this)-因此两个方法可以同时调用,一个线程将运行1,而另一个线程运行第二个线程。

但是,请注意,在您的代码中没有可用的竞争条件,因为竞争条件需要写操作,而这在这些方法中不存在。

梅玉堂
2023-03-14

那么为什么线程-1中的actBusy()调用没有被阻止?

因为您的actBusy方法未同步。即使获得了类级锁,也可以调用非同步静态方法。

将方法标记为< code>synchronized的目的是启用锁。只有声明为synchronized的方法才受这些锁的约束。因此,如果您获取了一个锁(假设是类级别的锁),那么任何< code >非同步方法都会像以前一样工作,并且不知道锁被获取了。这允许您决定哪些方法需要被阻止,哪些不需要。

 类似资料:
  • 本文向大家介绍java synchronized同步静态方法和同步非静态方法的异同,包括了java synchronized同步静态方法和同步非静态方法的异同的使用技巧和注意事项,需要的朋友参考一下 java synchronized 详解 synchronized关键字有两种用法,一种是只用于方法的定义中,另外一种是synchronized块,我们不仅可以使用synchronized来同步一个对

  • 问题内容: 任何人都可以解释以下语句吗……“静态同步方法和非静态同步方法不会互相阻塞-它们可以同时运行” 问题答案: 锁定对象在静态方法和非静态方法上有所不同。静态方法将Class对象用作锁(锁obj:),而非静态方法将实例对象用作锁,此时方法的调用已绑定到该对象(锁obj:)。

  • 我正在编写的代码需要在几个静态方法之间进行一些同步。我的目标是阻止执行这些方法中的任何一个,如果其中一个执行。例如: 现在让我们假设下面的代码是从代码中的某个地方执行的: 我的问题是: > 它实际上是同步的吗?methodA和methodB不会同时运行吗? 如果是,methodA调用methodB会不会造成死锁?

  • 问题内容: 在Java中同步静态方法和非静态方法有什么区别?有人可以举例说明吗?在同步方法和同步代码块方面也有什么区别吗? 问题答案: 我将尝试添加示例以使这一点更加清楚。 如前所述,Java中的同步是Monitor概念的实现。当您将代码块标记为同步时,可以使用一个对象作为参数。当执行线程进入这样的代码块时,它必须首先等待,直到同一对象上的同步块中没有其他执行线程。 在上面的示例中,一个正在运行的

  • 主要内容:1 什么是Java静态同步方法,2 没有静态同步方法的问题,3 静态同步方法的例子1,4 静态同步方法的例子21 什么是Java静态同步方法 如果将任何静态方法设置为synchronized(同步),则锁定的是类而不是对象。 2 没有静态同步方法的问题 假设有两个共享类(例如:Table类)的对象,分别名为object1和object2。在使用同步方法和同步代码块的情况下,t1和t2或t3和t4之间不会存在干扰,因为t1和t2都引用了一个具有单个锁,但是t1和t3或t2和t4之间可能存

  • 问题内容: 这是我在此链接上找到的一段文字。 “避免锁定静态方法 最糟糕的解决方案是将“ synchronized”关键字放在静态方法上,这意味着它将锁定此类的所有实例。” 为什么同步静态方法会锁定该类的所有实例?它不应该锁定课程吗? 问题答案: 这是我的测试代码,表明您是正确的,并且本文有点过分谨慎: 印刷品: 因此与实例的方法无关… 当然,如果整个系统都使用这些方法,那么您可以期望它们对多线程