【问题标题】:Running an object with a synchronized method and normal method, concurrently?同时运行具有同步方法和普通方法的对象?
【发布时间】:2017-03-14 17:07:36
【问题描述】:

难道只是两个同步的方法不能同时运行吗?

例如,有人编写了 2 个 Java 类。

public class A {
    public synchronized void a1(){   
    //do something   }
    public void a2(){
    //do something   }
    public synchronized int a3(){
    int var = 0;
    //do something changing var
    return var;   } }


public class B {

  public void b1(){
    //do something
  }


  public synchronized int b2(){   
    int var = 0;
    //do something changing var
    return var;
  }

  public void b3(){
    //do something
  }
}

使用main方法,

public static void main(String[] args){
  A firstA = new A();
  A secondA = new A();
  B firstB = newB();

  //create some threads that perform operations on firstA, secondA and first B and start them
}

假设它们并行运行并在创建的对象上调用方法,并假设其他机制当前没有阻止这些方法运行。

在我给出的示例中的方法中,如果由 2 个不同的线程同时调用,是否有任何方法不能并发运行?

通过同时运行我的意思是,它们将被排序,以便一个将在另一个开始之前完成。

【问题讨论】:

    标签: java concurrency synchronized


    【解决方案1】:

    假设不涉及其他同步,唯一会相互排除的调用是:

    1. firstA.a1() 与 firstA.a1()
    2. firstA.a1() 与 firstA.a3()
    3. secondA.a1() 与 secondA.a1()
    4. secondA.a1() 与 secondA.a3()
    5. firstB.b2() 与 firstB.b2()

    这是因为同步块必须使用相同的锁才能相互影响。当您将整个方法标记为synchronized 时,锁定对象将是this 的值。所以firstA 中的方法将完全独立于secondA 或firstB 的方法,因为它们使用不同的锁。

    代码中未标记synchronized 的方法甚至根本不会尝试获取任何锁,它们可以随时运行。

    请注意,互斥只是多线程的一个方面。为了让您的程序正常运行,您还必须考虑可见性和安全发布等问题。

    【讨论】:

      【解决方案2】:

      当然,答案取决于当你“做某事”时,你“做了”什么“某事”,而由于你没有表现出来,所以没有人可以回答。当您忽略重要信息时,就会发生这种情况。不要遗漏重要信息。

      我们可以说,A 中的同步方法与B 中的同步方法使用的锁不同。

      如果多个线程访问相同的数据,那么它们必须相互同步。线程彼此同步的唯一方法是使用相同的同步方式。如果这是使用synchronized,那么它们必须在同一个监视器上同步(锁定)。因此,如果A 方法和B 方法从不同的线程访问相同的数据,那么谁能从您显示的内容中判断它们是否做了?那么它们将不会如图所示工作。

      如果任何不同步的方法从不同的线程访问相同的数据,而你没有展示的部分没有其他有效的同步手段,那么它们将不起作用。

      这一切都取决于您决定不向我们展示的内容。

      【讨论】:

      • 公平地说,您可以在不知道它们做什么的情况下回答互斥问题(假设方法本身不做任何额外的锁定)。但正如你所说,这仍然无法回答正确性问题。
      • “假设方法本身不做任何额外的锁定”?但你不能假设,我说出来了。您的评论相当于“您可以在不知道他们做什么的情况下回答互斥问题,除非他们做了我们不知道的某些事情”。
      • 来吧,这不是一个很大的假设。显然,如果我复制执行同步的代码,并询问同步,我省略的位将不包含同步。
      • 假设没有大小。这是一个假设。您没有关于您的假设正确或不正确的信息。即使假设“没有那么大”,也足以将正确的方法变成错误的方法。
      • 当然有,这就是我们有奥卡姆剃刀的原因。不过没关系,我已经回答了这个问题。
      【解决方案3】:

      所有这些都可以同时运行而不会相互干扰。 因为每个线程处理不同的实例,所以它们无需等待如此同步的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        • 2021-10-19
        相关资源
        最近更新 更多