JAVA:同步关键字块是代码块的哪一部分?并解释这一僵局

JAVA:同步关键字块是代码块的哪一部分?并解释这一僵局,java,multithreading,oracle,deadlock,Java,Multithreading,Oracle,Deadlock,我必须回答以下问题: 一,。同步方法的代码的哪一部分,同步块? 例如: public class example{ public synchronized void f1(){ //some code.... f2(); } public synchronized void f2() { //some code... } } public void main(String[[] args) { Thread t1 = ne

我必须回答以下问题:
一,。同步方法的代码的哪一部分,同步块?
例如:

public class example{

  public synchronized void f1(){
    //some code....
     f2();
    }
    public synchronized void f2()
    {
      //some code...
    }
}
public void main(String[[] args)
{
   Thread t1 = new Thread(new Runnable()
   {public void run(){f1();)},
          t2 = new Thread(new Runnable()
   {public void run(){f2();};
   t1.start();
   t2.start();

}
所以在t1启动后,t2不能启动,因为它在等待t1。但是t1开始做f2,这是否意味着t2可以进入f1

如果可以,请解释一下这个死锁示例。我不明白。资料来源:


死锁示例:由于两个线程(执行一个进程的实例,甚至一些操作系统称之为轻量级进程)获得相同的锁,因此其中一个线程将始终获得锁,而另一个线程必须等到首先获得锁的线程(这是由JVM决定的,将JVM视为操作系统——必须有人保证锁的原子性,这取决于JVM)完成。 在本例中,一个线程将执行bow(),然后执行bowBack(),但在执行bowBack()时,另一个线程已对同一个锁执行了获取(通过调用bow()),使另一个线程处于等待状态,这取决于第一个线程,并且在调用bowBack()时第一个线程依赖于同一个锁-发生了循环依赖,即死锁

从oracle文档:

首先,不可能两次调用同步方法 在同一对象上进行交叉。当一个线程正在执行 对象的同步方法,调用 同一对象块的同步方法(暂停执行) 直到第一个线程处理完对象

该示例进一步指出,死锁极有可能发生,这意味着死锁不必发生。这是因为获得锁的第一个线程可以在第二个线程获得锁之前完成其bowBack(),即调用bow()(我使用acquire the lock作为操作系统理论中的术语,这一次是用原始语言编写的),由JVM决定哪个线程可以在什么时候执行(线程执行方案的实际调度,以及更改执行线程(称为上下文切换)代价太高,因此JVM可能会决定让第一个线程执行更长的周期,而死锁的结果不会发生。考虑线程调度一个是最好的,把它看作是一个相当随机的事情,如果死锁会发生,它迟早会,一个程序运行。(或其他类型的循环,例如,产生两个线程的方法,如示例中所示)可能会产生死锁,但另一个可能不会。多线程处理主要是考虑锁定什么,而不是以可能产生死锁的方式组合锁

也许您应该尝试让示例不死锁,例如让一个线程休眠一段时间(例如,在进入bow之前尝试1毫秒,然后说gaston.bow())看看会发生什么,记住这样做没有任何保证,睡眠一个线程实际上并不能使代码线程安全,死锁只会发生得更少


然后引入更多线程来执行bow()怎么样-睡眠真的有帮助吗,还是只是推迟了问题……?

Java中的一个
同步的
方法锁定了整个方法,更重要的是,它锁定了调用该方法的对象的实例。这意味着同一对象中的两个同步方法共享同一个锁,因此不能并发y由不同的线程执行

例如,在下面的班级

public class myClass
{
  synchronized void method1()
  {

  }

  synchronized void method2()
  {

  }
}
method1()
method2()
不能在同一对象上同时调用,因为代码相当于:

public class myClass
{
  void method1()
  {
    synchronized(this)
    {
      // ...
    }
  }

  void method2()
  {
    synchronized(this)
    {
      // ...
    }
  }
}
如果希望两种方法在不同的锁上独立同步,则可以执行以下操作:

public class myClass
{
  private final Object method1Lock = new Object();
  private final Object method2Lock = new Object();

  void method1()
  {
    synchronized(method1Lock)
    {
      // ...
    }
  }

  void method2()
  {
    synchronized(method2Lock)
    {
      // ...
    }
  }
}

`调用bowBack()时,第一个线程和第一个线程依赖于同一个锁。`你是说bow()和bowBack()使用的是同一个锁吗?这没有任何意义。为什么两个不同的函数会使用同一个锁?在这两个问题中,第一个问题不清楚(不编译,很难说你想要什么),关于鞠躬示例的问题已经得到了回答。因此,当激活
alphonse.bow(gaston);
时,alphonse被锁定在他的
bow()
函数中,并且在退出
bow()之前不能执行任何其他操作(例如
bowBack()
函数?不,这是因为当
alphonse
尝试调用
gaston.bowBack()
时无法完成,因为
gaston
由于第二个线程调用
gaston.bow()
而被锁定。因此gaston正在等待
alphonse.bow()
完成(以便调用
alphonse.bowBack())
),阿尔方斯正在等待
gaston.bow()
public class myClass
{
  private final Object method1Lock = new Object();
  private final Object method2Lock = new Object();

  void method1()
  {
    synchronized(method1Lock)
    {
      // ...
    }
  }

  void method2()
  {
    synchronized(method2Lock)
    {
      // ...
    }
  }
}