0

好的,假设我有一个具有线程安全实现的 Java Math 类。线程 A 现在正在执行 SetValue(1),它会导致 Math 类被锁定。如果线程 B 同时尝试使用 GetValue() 访问,会发生什么情况?会不会等到锁释放或者方法请求会直接终止,没有警告或异常?

public class Math {
      private static int value = 0;

      public synchronized static void setValue(int value) {
           Math.value = value;
      }

      public synchronized static int getValue() {
           return value;
      }
}
4

4 回答 4

3

是的,第二个线程将等到锁再次可用。如果锁永远不可用,您将遇到活性问题,并且您的第二个线程将挂起。

JLS 17.1中有更详细的描述:

同步方法在调用时会自动执行锁定操作;在锁定操作成功完成之前,它的主体不会被执行。[...] 如果方法主体的执行正常或突然完成,则会在同一监视器上自动执行解锁操作。

另请注意:

Java 编程语言既不防止也不要求检测死锁条件。线程持有(直接或间接)多个对象锁的程序应该使用传统技术来避免死锁,如有必要,创建不会死锁的更高级别的锁定原语。

于 2012-11-27T16:23:51.517 回答
1

一个小插图:

public class Math {

 private static int value = 0;

 public synchronized static void SetValue(int _value) throws InterruptedException {

  Thread.sleep(1000L);
  value = _value;
 }

 public synchronized static int GetValue()  {

  return value;
 }

 public static void main(String[] args) {

  new Thread(new Runnable() {

   @Override
   public void run() {

    try {
     SetValue(-100);
    } catch (InterruptedException e) {
     // ignore
    }
   }
  }).start();

  new Thread(new Runnable() {

   @Override
   public void run() {

    System.out.println("GetValue() = " + GetValue());
   }
  }).start();
 }
}

输出是:

GetValue() = -100

这意味着第二个线程将等待第一个线程在休眠一秒钟并将其设置value100.

于 2012-11-27T16:29:31.960 回答
1

如果需要,它将永远等待第一个线程释放锁。

于 2012-11-27T16:23:41.323 回答
1

Thread添加到等待队列中,并且在Thread A执行该SetValue方法之前一直保持在那里,并且不会释放锁。

一旦Thread A释放锁,Thread B就会收到通知,之后可以继续。

另请注意,当Thread A进入该SetValue方法时,它会在该类的所有同步方法上获取锁。所以,在方法执行完成之前Thread B不能执行任何操作,并逐渐释放锁。synchronized methodThread ASetValue

还有一件事,不能保证一旦锁被释放Thread B就会立即开始执行该方法。GetValue这完全取决于 CPU,它何时将资源分配给线程 B。


PS: - 请在您的代码中遵循 Java 命名约定。您的方法名称应以lowercase字母开头。所以,你的方法应该是getValueand setValue

于 2012-11-27T16:24:11.230 回答