好的,我说我有一个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;
}
}
答案 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
字母开头。因此,您的方法应为getValue
和setValue
。
答案 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
。