在Java中编写一次一个锁

时间:2009-06-01 18:32:06

标签: java concurrency

我正在尝试实现Java锁类型,它执行以下操作:

  1. 默认情况下,线程不会传递锁。 (与普通锁相反,只要没有锁就可以获得锁。)
  2. 如果只有一个线程正在等待锁定,那么该线程中的执行将停止
  3. 如果多个线程正在等待锁定,则允许等待时间最长的线程继续执行。
  4. 我正在使用AbstractQueuedSynchronizer来实现它。允许最旧的线程通过的转换如下所示:

    //inner class inside Lock
    private static class Sync extends AbstractQueuedSynchronizer {
        public Sync(){
            setState(-1);
        }
    
        public boolean tryAcquire(int ignore) {
            if (getState() == 1) return false;
    
            Thread first = getFirstQueuedThread();
            if (first != null &&
                first != Thread.currentThread()) {
                setState(0);
                return false;
            }
            return compareAndSetState(0, 1);
    

    我看到的问题是,当我调用setState(0)但返回false时,Sync对象再也没有第一个线程tryAcquire。我需要使用SharedMode吗?这个问题有更好的解决方案吗?

    这是我称之为“Valve”的实现的一部分,我想用它来进行长轮询AJAX响应。我有一个线程等待阀门变为“加压”的部分 - 有数据发送到客户端)但是获取最旧的线程似乎很难,除非我不使用AbstractQueuedSynchronizer,我真的不喜欢我想写一个基础锁实现。

2 个答案:

答案 0 :(得分:1)

查看ReentrantLock类(http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html)。

您可以将此锁定对象保留为类中的私有变量,并使用它来执行您需要执行的任何操作。我不太确定如何在不了解您的代码的情况下实现这一点,但是这个Lock对象具有您提供帖子中提到的行为所需的所有方法。

要跟踪线程等待的时间,您可能需要一起黑客攻击才能跟踪它。我认为Thread类不提供这种功能。

答案 1 :(得分:0)

您是否看过这个link

  

公平锁定

     

下面显示了之前的Lock类变成了一个名为FairLock的公平锁。您会注意到,与前面显示的Lock类相比,实现在同步和wait()/ notify()方面有所改变。

     

从前一个Lock类开始,我是如何从这个设计开始的,是一个涉及几个增量设计步骤的较长故事,每个步骤都解决了上一步的问题:嵌套监视器锁定,滑动条件和错过信号。本文不讨论该讨论以使文本简短,但每个步骤都在相关主题的文本中讨论(参见上面的链接)。重要的是,每个调用lock()的线程现在都已排队,并且只有队列中的第一个线程被锁定才能锁定FairLock实例(如果它已解锁)。所有其他线程都停在等待,直到它们到达队列的顶部。