当第一个线程锁定类时,第二个线程发生了什么

时间:2012-11-27 16:21:56

标签: java multithreading thread-safety locking

好的,我说我有一个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 个答案:

答案 0 :(得分:3)

是的,第二个线程将等到锁再次可用。如果锁定永远不可用,则会出现活动问题,并且第二个线程将挂起。

JLS 17.1中详细介绍了

  

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

另请注意:

  

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

答案 1 :(得分:1)

如果有必要,它会等待第一个线程释放锁。

答案 2 :(得分:1)

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

只要Thread A释放锁定,就会通知Thread B,之后可以继续。

另请注意,当Thread A进入SetValue方法时,它会获取该类的所有同步方法的锁定。因此,在Thread B执行synchronized method方法之前,Thread A无法执行任何SetValue,并逐渐释放锁定。

还有一件事,一旦发布锁定,就不能保证Thread B会立即开始执行GetValue方法。这一切都取决于CPU,它何时将资源分配给线程B.


P.S: - 请在您的代码中遵循Java命名约定。您的方法名称应以lowercase字母开头。因此,您的方法应为getValuesetValue

答案 3 :(得分: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

这意味着第二个线程将等待第一个线程在休眠一秒后将其唤醒并将value设置为100