gst*_*low 25 java concurrency multithreading synchronization thread-safety
我在项目中面对以下代码:
synchronized (Thread.currentThread()){
//some code
}
Run Code Online (Sandbox Code Playgroud)
我不明白使用synchronized的原因currentThread
.
两者之间有什么区别吗?
synchronized (Thread.currentThread()){
//some code
}
Run Code Online (Sandbox Code Playgroud)
只是
//some code
Run Code Online (Sandbox Code Playgroud)
你能提供一个显示差异的例子吗?
更详细的代码如下:
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(timeInterval);
}
Run Code Online (Sandbox Code Playgroud)
看起来就像Thread.sleep(timeInterval)
.这是真的吗?
Evg*_*eev 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);
}
Run Code Online (Sandbox Code Playgroud)
块A和B不能同时运行,因此在给定的测试中,"A"或"B"输出将延迟5秒,其中一个将首先是未定义的
虽然这几乎肯定是一个反模式,应该以不同的方式解决,但你的直接问题仍然需要一个答案.如果您的整个代码库永远不会在Thread
除了之外的任何实例上获得锁定Thread.currentThread()
,那么这个锁实际上永远不会被争用.但是,如果你有其他任何地方
synchronized (someSpecificThreadInstance) { ... }
Run Code Online (Sandbox Code Playgroud)
然后这样一个块将不得不与你所显示的块争用相同的锁.可能确实会发生线程到达synchronized (Thread.currentThread())
必须等待其他线程放弃锁定.
基本上,synchronized
块的存在与不存在之间没有区别.但是,我可以想到一种可能为这种用法带来其他意义的情况.
这些synchronized
块具有一个有趣的副作用,即在进入和离开块之前,运行时会创建一个内存屏障.内存屏障是对CPU的一种特殊指令,它强制执行多个线程之间共享的所有变量以返回其最新值.通常,线程使用自己的共享变量副本,并且其值仅对此线程可见.内存屏障指示线程以某种方式更新值,以便其他线程可以看到更改.
因此,在这种情况下同步块不会进行任何锁定(因为没有锁定和等待情况的真实情况,至少我无法想到)(除非本答案中提到的用例被解决),但是相反,它强制执行共享字段的值以返回其最新值.但是,如果与所讨论的变量一起使用的代码的其他位置也使用内存屏障(比如synchronized
在更新/重新分配操作周围具有相同的块),则这是正确的.尽管如此,这还不是避免竞争条件的解决方案.
如果您有兴趣,我建议您阅读本文.它是关于C#和.NET框架中的内存障碍和锁定,但Java和JVM的问题类似(除了volatile字段的行为).它帮助我理解线程,易失性字段和锁一般如何工作.
必须考虑到这种方法中的一些严肃的考虑因素,这些问题在本答案的下方评论中提到过.
归档时间: |
|
查看次数: |
3206 次 |
最近记录: |