如何通过synchronized方法

时间:2015-06-18 04:34:57

标签: java deadlock

我遇到了像Deadlocks and Synchronized methods这样的问题。在这种情况下, methodA methodB A.last()都必须是同步方法。因此,我将通过方法 B.last()中的删除同步来解决此问题。这个解决方案中的任何僵局?你能告诉我任何解决方案吗?

Class A
{
  synchronized void methodA(B b)
  {
    b.last();
  }

   synchronized void last()
  {
    System.out.println(“ Inside A.last()”);
  }
}

Class B
{
  synchronized void methodB(A a)
  {
    a.last();
  }

  synchronized void last()
  {
    System.out.println(“ Inside B.last()”);
      }
}


Class Deadlock implements Runnable 
{
  A a = new A(); 
  B b = new B();

  // Constructor
  Deadlock()
  {
    Thread t = new Thread(this); 
    t.start();
    a.methodA(b);
  }

  public void run()
  {
    b.methodB(a);
  }

  public static void main(String args[] )
  {
    new Deadlock();
  }
}

2 个答案:

答案 0 :(得分:0)

您可以在两种方法之间使用常见的互斥锁,例如ReentrantLock或同步块,而不是同步。

ReentrantLock示例:

Class A
{
  A(Lock lock) {
    this.lock = lock;
  }
  private Lock lock;

  void methodA(B b)
  {
    lock.lock();
    try {
      b.last();      
    } finally {
      lock.unlock();
    }
  }

  void last()
  {
    lock.lock();
    try {
      System.out.println(“ Inside A.last()”);
    } finally {
      lock.unlock();
    }
  }
}

Class B
{
  B(Lock lock) {
    this.lock = lock;
  }
  private Lock lock;
  void methodB(A a)
  {
    lock.lock();
    try {
      a.last();   
    } finally {
      lock.unlock();
    }
  }

  void last()
  {
    lock.lock();
    try {
      System.out.println(“ Inside B.last()”);     
    } finally {
      lock.unlock();
    }
  }
}


Class Deadlock implements Runnable 
{
  Lock lock = new ReentrantLock();
  A a = new A(lock); 
  B b = new B(lock);

  // Constructor
  Deadlock()
  {
    Thread t = new Thread(this); 
    t.start();
    a.methodA(b);
  }

  public void run()
  {
    b.methodB(a);
  }

  public static void main(String args[] )
  {
    new Deadlock();
  }
}

synchronized块示例:

Class A
{
  A(Object lock) {
    this.lock = lock;
  }
  private Object lock;

  void methodA(B b)
  {
    synchronized(lock){
      b.last();      
    }
  }

  void last()
  {
    synchronized(lock){
      System.out.println(“ Inside A.last()”);
    }
  }
}

Class B
{
  B(Object lock) {
    this.lock = lock;
  }
  private Object lock;
  void methodB(A a)
  {
    synchronized(lock){
      a.last();   
    }
  }

  void last()
  {
    synchronized(lock){
      System.out.println(“ Inside B.last()”);     
    }
  }
}


Class Deadlock implements Runnable 
{
  Object lock = new Object();
  A a = new A(lock); 
  B b = new B(lock);

  // Constructor
  Deadlock()
  {
    Thread t = new Thread(this); 
    t.start();
    a.methodA(b);
  }

  public void run()
  {
    b.methodB(a);
  }

  public static void main(String args[] )
  {
    new Deadlock();
  }
}

答案 1 :(得分:0)

通常,为了避免死锁,要么只使用一个锁,要么确保始终以相同的顺序获取锁。

假设您决定A总是必须在B之前被锁定,那么您的示例的一个微创错误修复(假设没有其他任何内容与AB对象同步)将在类{{ 1}}:

B

这样,如果需要两个锁,则始终首先获取A的锁定,不会导致死锁。

您也可以对Java 5+ void methodB(A a) { synchronized(a) { synchronized(this) { // do whatever was in methodB before, including... a.last(); } } } 锁执行相同的操作。删除不需要的同步当然也是解决死锁的一种选择(但如果需要同步,则会导致竞争条件,而不是死锁)。