【问题标题】:How to implement a spinlock to avoid blocking如何实现自旋锁以避免阻塞
【发布时间】:2014-12-29 19:51:50
【问题描述】:

考虑以下代码:

// Below block executed by thread t1
synchronized(obj) {
   obj.wait(0);
}

// This block executed by thread t2
synchronized(obj) {
    obj.notify();
}

我知道在上面的代码中,如果t1 拥有同步块的所有权,同时如果线程t2 尝试获取同步块,那么t2 会等待内核等待。 我想避免这种情况并在块之前旋转t2,直到t1 调用等待并留下块的所有权。这可能吗?

【问题讨论】:

  • 请在点击提交之前花更多的精力来格式化您的帖子 - 使用预览查看帖子的外观,并且仅在您希望它看起来像 回答了这个问题。
  • 此外,您是否有证据表明这实际上会导致您的代码出现问题?自旋锁很少是正确的解决方案 - 请记住,t1 将在调用wait() 时立即放弃锁,因此 t2 阻塞的机会窗口非常小。
  • 你为什么要这样做?相反,在一个线程上等待锁,您将有一个线程在等待锁,同时浪费 CPU 周期。
  • 我对这个代码块的使用太啰嗦,多个线程等待并通知,我不希望我的线程进入内核等待,而是我可以旋转一点并获得所有权
  • 同意 OP 应该扩展“为什么” - 但如果从来没有很好的需求,则不会创建 java.util.concurrent.locks 包。

标签: java multithreading thread-synchronization spinlock


【解决方案1】:

JVM 不需要将锁定同步块的入口实现为硬块和上下文切换。 It has the option of using lighter weight methods, such as spin locks。事实上,Oracle JVM 转到some lengths 以避免阻塞。所以你可能会发现 JVM 已经为你做了这个优化。如果没有,那可能是因为 JVM 有证据表明自旋锁是个坏主意。

【讨论】:

  • 感谢 Raedwald,您能否分享任何暗示这一点的链接。
【解决方案2】:
import java.util.concurrent.atomic.AtomicBoolean;

public class SpinLock {

   private AtomicBoolean locked = new AtomicBoolean(false);

   public void lock() {
      while (!locked.compareAndSet(false, true));
   }

   public void unlock() {
      locked.set(false);
   }
}

【讨论】:

  • 不需要 CAS 来实现 SpinLock。通过诸如 while (getAndSet(true) == true) 之类的方法更改循环可能会依赖于更轻松的 xchg 指令。但它还有更多内容,可能最好依靠 JVM 来做正确的事情。
【解决方案3】:

它很容易实现spinlock in Java。这里的想法是利用 Lock 接口的 tryLock() 方法。

 import java.util.concurrent.locks.ReentrantLock;

public class SpinLock extends ReentrantLock{

public SpinLock() {
  super();
 }


 public void lock() {
  while(!super.tryLock()) {
    // Do Nothing
  }

 }

 public void unlock() {
  super.unlock();
 }

}

参考:https://tech693.blogspot.com/2018/08/java-spin-lock-implementation.html

【讨论】:

    【解决方案4】:

    是的,您可以随心所欲。

    接口java.util.concurrent.locks.Lock(如ReentrantLock)的实现允许您使用tryLock 方法(从循环调用)忙等待锁定。

    要实现waitnotify 功能,您可以在Lock 上调用newCondition 方法以获取Condition 对象。 Condition 接口具有 awaitsignal/signalAll 方法,其工作方式类似于 waitnotify/notifyAll

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      相关资源
      最近更新 更多