[英]Java: synchronize keyword doesn't block object on different thread
public class SynchronizeTest {
public synchronized void methodA() {
System.out.println("calling method a ...");
sleep(2000);
System.out.println("ending method a");
}
public void methodC() {
System.out.println("calling method C");
new Thread(new Runnable() {
@Override
public void run() {
methodA();
}
}).start();
sleep(100);
System.out.println("end method C");
}
public static void main(String[] args) {
new SynchronizeTest().methodC();
}
static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
起初,我猜是因为我synchronize
方法A,这意味着整个对象将被锁定,直到该方法完成为止。 所以答案应该是:
calling method C
calling method a
ending method a
ending method C
但是事实证明,结果是这样的:
calling method C
calling method A
ending method C
ending method A
这意味着methodA
不会像我猜的那样锁定对象。 请告诉我为什么。
在实例方法上使用synchronized
关键字时,这意味着该对象上的方法当时只能由一个线程调用。
这并不意味着对对象的所有方法进行任何形式的锁定,即可以在该方法的调用期间调用其他实例方法-当您在执行操作时异步调用它时,也更容易。
既然你是你的线程内调用它methodC
,并在睡眠时间methodA
比结束前的一个更大的methodC
,您的电流输出是非常可能发生的每一次。
这是相关的文档报价(请参阅此处的页面):
使得方法同步具有两个作用:
首先,不可能在同一对象上两次调用同步方法。 当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程对该对象完成。
其次,当同步方法退出时,它会自动建立与先后发生的关系,并随后对同一对象调用同步方法。 这保证了对象状态的更改对所有线程都是可见的。
注意
您可能需要join
调用methodA
的线程,以确保在执行methodC
的最后一条语句之前终止其执行。
首先,您有2个线程1)main和2)您创建的线程(假设为thread1)。 现在发生的事情是使methodA同步,因此当线程1到达那里时它将保留在该方法中并尝试完成执行,但同时主线程可以进一步处理并打印最后的C语句。因为您在方法中添加了sleep调用,这导致thread1睡眠2秒。 所以输出将是C(主线程),a(您的线程),C(主线程),a(您的线程)
请阅读以下内容: https : //docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html如前所述,不可能对同一对象的两次同步方法调用进行交织。 当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程对该对象完成。 这意味着该对象将被其他同步方法锁定。 同步methodC也不是一个好主意。 它将为您提供以下输出:调用方法C /调用方法a /结束方法a /结束方法C。为了获得所需的输出,可以使用以下代码:
public class SynchronizeTest implements Runnable{
public synchronized void methodA() throws InterruptedException {
System.out.println("calling method a ...");
Thread.sleep(2000);
System.out.println("ending method a");
this.notify();
}
public synchronized void methodC() throws InterruptedException {
System.out.println("calling method C");
new Thread(new Runnable() {
@Override
public void run() {
methodA();
}
}).start();
this.wait();
System.out.println("end method C");
}
public static void main(String[] args) throws InterruptedException {
new Test().methodC();
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
关键字synchronized
意味着防止不同线程使用相同变量时发生的错误。 锁定线程根本没有任何意义,因为您可以随后调用方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.