gpt4 book ai didi

java - 同步方法和 block 的行为不同

转载 作者:行者123 更新时间:2023-12-01 09:05:59 25 4
gpt4 key购买 nike

我观察到使用同步方法或同步块(synchronized block)产生不同结果的场景。 从下面的代码:

class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("]");
}
}

class Caller implements Runnable{
String msg;
Callme target;
Thread t;

public Caller(Callme target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread(this, "Caller thread");
t.start();
}

@Override
public void run() {
synchronized(target) {
target.call(msg);
new Callme().call(msg);
}
}

}

public class Test {

public static void main(String[] args) throws InterruptedException {
Callme obj = new Callme();

new Caller(obj, "thread1");
new Caller(obj, "thread2");
new Caller(obj, "thread3");

Thread.currentThread().join();
}
}

当我在 Caller::run 方法中使用同步块(synchronized block)时,输出同步如下:

[thread1]
[thread1]
[thread3]
[thread3]
[thread2]
[thread2]

但是当我对 Callme::call 方法使用同步方法而不是同步块(synchronized block)时,输出不是同步的:

[thread1]
[thread1[thread2]
]
[thread3[thread2]
]
[thread3]

我的期望是两种情况下的输出不应同步,因为我在调用“Callme::call”方法时使用不同的对象

这让我质疑我对同步块(synchronized block)概念的理解?

最佳答案

同步方法相当于 synchronized(this) -block 表示整个方法的长度,但是您的代码使用 synchronized(target) ,和targetCallme 的共享实例。换句话说:同步的对象不同,所以行为也不一样。

如果您使用 synchronized(target) ,这意味着所有线程在Callme的同一个实例上同步。所以它们的行为是串行的:一个线程将持有 Callme 的监视器实例在 Caller.run 的整个持续时间内方法,因此实际上线程是一个接一个执行的。

在同步方法的情况下,每个线程在它们自己的 Caller 实例上同步。 ,因此实际上没有序列化(除了写入 System.out )。

一些补充说明:

  • 调用 Thread.currentThread().join()这是一个坏主意,因为它会自行等待
  • 一般情况下不要创建和启动 Thread Runnable 中的实例将由该线程运行的实现:您将失去对该线程的访问权限。特别是不要在构造函数中执行此操作,因为您要将部分构造的对象发布到 Thread ,这在此代码中并不是一个大问题,但可能会在更复杂的应用程序中导致细微的错误。

关于java - 同步方法和 block 的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41283695/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com