Java 如何实现自旋锁以避免阻塞
考虑以下代码:Java 如何实现自旋锁以避免阻塞,java,multithreading,thread-synchronization,spinlock,Java,Multithreading,Thread Synchronization,Spinlock,考虑以下代码: // 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调用等待并离开块
// 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调用等待并离开块的所有权。有可能吗?是的,有可能做你想做的事 接口java.util.concurrent.locks.Lock(如ReentrantLock)的实现允许您使用从循环调用的tryLock方法繁忙地等待锁
要实现等待和通知功能,可以调用方法newCondition on Lock来获取条件对象。Condition接口具有wait和signal/signalAll方法,其工作方式类似于wait和notify/notifyAll。JVM不需要将锁定的同步块的条目作为硬块和上下文开关实现。事实上,oraclejvm使用户可以避免阻塞。因此,您可能会发现JVM已经为您进行了这种优化。如果没有,那可能是因为JVM有证据表明自旋锁是个坏主意。它很容易实现。这里的想法是利用锁接口的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();
}
}
参考资料:在点击提交之前,请在格式化您的帖子方面投入更多的精力-使用预览查看帖子的外观,并且仅在您回答问题时,当它看起来像您希望的样子时才提交。此外,您是否有证据表明这实际上导致了代码中的问题?自旋锁很少是正确的解决方案-请记住,t1会在调用wait时立即放弃锁,因此t2阻塞的机会窗口非常小。为什么要这样做?相反,在一个线程上等待锁,你会有一个线程在等待锁,同时浪费CPU周期。我对这个代码块的使用太过频繁,多个线程等待并通知,我不希望我的线程进入内核等待,而是希望我可以旋转一点,获得OP应该在why上展开的所有权协议-但是如果从来没有很好的需求,那么就不会创建java.util.concurrent.locks包。谢谢Raedwald,你能分享任何建议这个的链接吗?CAS不需要实现自旋锁。通过while getAndSettrue==true之类的方式更改循环可能会依赖于更简单的xchg指令。但是还有更多的问题,最好依靠JVM来做正确的事情。
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);
}
}