在Java中使用synchronized(Thread.currentThread()){…}的目的是什么?

我在项目中面对以下代码:

synchronized (Thread.currentThread()){ //some code } 

我不明白在currentThread上使用synchronized的原因。

两者之间有什么区别吗?

 synchronized (Thread.currentThread()){ //some code } 

只是

 //some code 

你能提供一个显示差异的例子吗?

UPDATE

更详细的代码如下:

 synchronized (Thread.currentThread()) { Thread.currentThread().wait(timeInterval); } 

它看起来就像Thread.sleep(timeInterval) 。 这是真的吗?

考虑一下

  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秒,其中一个将首先是未定义的

虽然这几乎肯定是一个反模式,应该以不同的方式解决,但你的直接问题仍然需要一个答案。 如果您的整个代码库永远不会获得除Thread.currentThread()之外的任何Thread实例的锁定,那么这个锁实际上永远不会被争用。 但是,如果你有其他任何地方

 synchronized (someSpecificThreadInstance) { ... } 

然后这样一个块将不得不与你显示的块争用相同的锁。 可能确实发生了达到synchronized (Thread.currentThread())线程必须等待其他线程放弃锁定。

基本上, synchronized块的存在与否之间没有区别。 但是,我可以想到一种可能为这种用法带来其他意义的情况。

synchronized块具有一个有趣的副作用 ,即在进入和离开块之前使运行时创建内存屏障 。 内存屏障是对CPU的一种特殊指令,它强制执行多个线程之间共享的所有变量以返回其最新值。 通常,线程使用其自己的共享变量副本 ,并且其值仅对此线程可见。 内存屏障指示线程以某种方式更新值,以便其他线程可以看到更改。

因此,在这种情况下同步块不会进行任何锁定(因为没有锁定和等待情况的真实情况,至少我无法想到) (除非本答案中提到的用例被解决),但是相反,它强制执行共享字段的值以返回其最新值。 但是,如果与所讨论的变量一起使用的代码的其他位置也使用内存屏障 (比如在更新/重新分配操作周围具有相同的synchronized块),则这是正确的。 尽管如此,这还不是避免竞争条件的解决方案

如果您有兴趣,我建议您阅读本文 。 它涉及内存障碍和C#以及.NET框架中的锁定,但Java和JVM的问题类似(除了volatile字段的行为)。 它帮助我理解线程,易失性字段和锁一般如何工作。

必须考虑到这种方法中的一些严肃的考虑因素,这些问题在本答案的下方评论中提到过。

  • 内存屏障并不意味着锁定。 访问仍然是非同步的,并且可能遇到竞争条件和其他潜在问题。 唯一的好处是线程能够在使用锁的情况下读取共享内存字段的最新值。 如果工作线程只读取值并且它只关心它们是最现有的,同时避免锁的开销 – 一些用例可能是高性能的同步数据处理算法,一些实践使用类似的方法。
  • 上述方法不可靠 。 根据Holger的评论 ,编译器可以在优化时消除锁定语句,因为它可能认为它们是不必要的。 这也将消除内存障碍。 然后代码将不会发出锁定,如果要使用锁定,或者目的是创建内存屏障,它将无法按预期工作。
  • 上面的方法也是不可靠的,因为运行时JVM可以在它可以certificate监视器永远不会被另一个线程获取时删除同步,如果代码永远不会在另一个不是当前线程的线程对象的线程对象上同步,那么这个构造就是如此。 因此,即使它在系统A上的测试期间有效,它也可能在系统B上的另一个JVM下失败。更糟糕的是,代码可能会工作一段时间,然后在应用优化时停止工作。
  • 现在保留代码的意图是模棱两可的,因此应该使用更明确和富有表现力的方法来实现其效果(参见Marko Topolnik的评论以供参考)。

您正在实现递归互斥锁

即同一个线程可以进入同步块,但不能进入其他线程。