【问题标题】:thread safety with two synchronized methods, one static, one non static具有两种同步方法的线程安全性,一种是静态的,一种是非静态的
【发布时间】:2014-11-20 12:43:43
【问题描述】:

如果一个类只有两个同步方法(静态或非静态),则认为该类是线程安全的。如果其中一种方法是静态的而另一种是非静态的怎么办?它仍然是线程安全的,还是如果多个线程调用这些方法会发生坏事?

有一些类似的线程,如static synchronized and non static synchronized methods in threads,它们描述了方法调用没有相互阻塞。但我很想知道线程安全世界中的坏事(如不一致的状态、竞争条件等)是否会发生。

编辑 1:
由于静态方法不能调用非静态方法,所以这边应该没有线程冲突。另一方面,如果非静态方法调用静态方法,它必须获取类锁。这仍然是线程安全的。因此,仅使用两种方法(一种是静态的,一种没有),我看不到任何线程冲突。是对的吗?换句话说,我能看到的唯一问题是当非静态方法访问一些静态变量时。但是,如果所有访问都是通过方法完成的,那么我看不到线程安全有任何问题。这些是我的想法。我不确定我是否在这里遗漏了一些东西,因为我对 Java 并发有点陌生。

【问题讨论】:

  • 这取决于您是如何实现监控对象的。您是否进行了对象锁定或类级别锁定?请分享您的代码。
  • @JayaAnanthram - 方法同步隐含地表示在类或实例对象上:P

标签: java multithreading static synchronized


【解决方案1】:

在 Java 中,如下:

public class MyClass
{
    public synchronized void nonStaticMethod()
    {
        // code
    }

    public synchronized static void staticMethod()
    {
        // code
    } 
}

等价于:

public class MyClass
{
    public void nonStaticMethod()
    {
      synchronized(this)
      {
          // code
      }
    }

    public void static staticMethod()
    {
      synchronized(MyClass.class)
      {
          // code
      }
    } 
}

如您所见,静态方法使用this 作为监视器对象,而非静态方法使用类对象作为监视器。

由于thisMyClass.class 是不同的对象,静态和非静态方法可以同时运行。


要“修复”这个问题,请创建一个专用的静态监视器对象并在静态和非静态方法中使用它:

public class MyClass
{
    private static Object monitor = new Object(); 

    public void nonStaticMethod()
    {
      synchronized(monitor)
      {
          // code
      }
    }

    public static void staticMethod()
    {
      synchronized(monitor)
      {
          // code
      }
    } 
}

【讨论】:

    【解决方案2】:

    如果其中一种方法是静态的而另一种是非静态的怎么办?它仍然是线程安全的,还是如果多个线程调用这些方法会发生坏事?

    可能会发生坏事。

    静态方法将锁定在类监视器上。实例方法将锁定在实例监视器上。由于使用了两个不同的锁对象,因此这两个方法可以从不同的线程同时执行。如果它们共享状态(即实例方法访问静态数据),您将遇到问题。

    【讨论】:

      【解决方案3】:

      如果其中一种方法是静态的而另一种是非静态的怎么办?它仍然是线程安全的,还是如果多个线程调用这些方法会发生坏事?

      同步与对象上的监视器(锁)一起工作。

      对于静态方法,它是Class's class 的对象,对于实例方法,它是this 或调用对象。

      由于两个对象都不同,因此同步静态和非静态方法在多线程的情况下不会相互阻塞。这两种方法将同时执行。

      【讨论】:

        【解决方案4】:

        如果其中一种方法是静态的而另一种是非静态的怎么办

        是的.. 可能会发生坏事。因为如果您在static 方法上同步,那么您将锁定Class object 的监视器而不是instance 类,即您将锁定MyClass.class。 而当您在实例(非静态)方法上同步时,您实际上将锁定 当前实例,即 this 。因此,您锁定了两个不同的对象。因此,该行为将是未定义并且肯定不正确

        PS:在多线程中,根据经验,请记住 - 如果坏事可能发生,它们就会发生

        【讨论】:

          【解决方案5】:

          如果……它仍然是线程安全的怎么办?

          没有完整的例子就无法回答这个问题。线程安全的问题从来都不是关于方法的问题:这是一个关于数据结构损坏和活性保证的问题。如果不知道所有不同的线程做什么、它们处理什么数据以及它们如何相互协调(同步),谁也不能说一个程序是否是线程安全的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-25
            • 1970-01-01
            • 1970-01-01
            • 2011-07-07
            • 1970-01-01
            • 2016-05-15
            • 2014-10-24
            • 1970-01-01
            相关资源
            最近更新 更多