我在项目中面对以下代码:
synchronized (Thread.currentThread()){
//some code
}
我不明白在currentThread
上使用synchronized的原因。
之间有什么区别吗?
synchronized (Thread.currentThread()){
//some code
}
只是
//some code
你能提供一个显示差异的例子吗?
更详细的代码如下:
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(timeInterval);
}
看起来只是Thread.sleep(timeInterval)
。这是真的吗?
答案 0 :(得分:25)
考虑这个
Thread t = new Thread() {
public void run() { // A
synchronized (Thread.currentThread()) {
System.out.println("A");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
}
};
t.start();
synchronized (t) { // B
System.out.println("B");
Thread.sleep(5000);
}
块A和B不能同时运行,因此在给定的测试中,“A”或“B”输出将延迟5秒,哪一个将首先未定义
答案 1 :(得分:9)
虽然这几乎肯定是一个反模式,应该以不同的方式解决,但你的直接问题仍然需要一个答案。如果您的整个代码库永远不会在除Thread
之外的任何Thread.currentThread()
实例上获得锁定,那么这个锁实际上永远不会被争用。但是,如果你有其他任何地方
synchronized (someSpecificThreadInstance) { ... }
然后这样一个块将不得不与你所显示的块争用相同的锁。到达synchronized (Thread.currentThread())
的线程可能必须等待其他线程放弃锁定。
答案 2 :(得分:6)
基本上synchronized
块的存在和不存在没有区别。但是,我可以想到一种可能对这种用法有其他意义的情况。
synchronized
块有一个有趣的副作用,导致在进入和离开块之前运行时创建内存障碍。内存屏障是对CPU的一种特殊指令,它强制执行多个线程之间共享的所有变量以返回其最新值。通常,线程使用其自己的共享变量的副本,并且其值仅对此线程可见。内存屏障指示线程以某种方式更新值,以便其他线程可以看到更改。
因此,在这种情况下,同步块不会执行任何锁定(因为没有真正的锁定和等待情况,至少我无法想到)(除非使用 - this answer中提到的案例已得到解决),但它强制执行共享字段的值以返回其最新值。但是,如果使用有问题的变量的代码的其他位置也使用内存屏障(比如在更新/重新分配操作周围具有相同的synchronized
块),则这是正确的。尽管如此,这仍然是不是解决方案以避免竞争条件。
如果您有兴趣,我建议您阅读此article。它是关于C#和.NET框架中的内存障碍和锁定,但Java和JVM的问题类似(除了volatile字段的行为)。它帮助我理解线程,易失性字段和锁一般如何工作。
必须考虑到这种方法中的一些严肃考虑因素,这些问题在本答案的下方评论中提到过。
答案 3 :(得分:1)
您正在实施递归互斥锁。
即。同一个线程可以进入同步块,但不能进入其他线程。