2013-05-10 60 views
15

我有一个LockManager管理多个线程的锁。有时线程是坏男孩,我必须杀死它们并要求LockManager释放所有的锁。然而,因为我在java中使用ReentrantLock这是不可能的,我不能解锁另一个线程拥有的锁。解锁其他线程拥有的锁java

我被迫使用锁(不能使用信号灯,它是作业的一部分)。有没有任何Java Lock实现允许我解锁其他线程拥有的锁?

到目前为止,我认为有三种选择:

  • 重新实施的方式,让我做这件事
  • 使信号灯和ReentrantLocks

额外之间某种映射的ReentrantLock您可能会觉得有用的来源:

回答

7

你是否被允许使用自己的Lock?这里有一个完全代理Lock的类,但是当它被告知强制解锁时,它只是用一个替代它代理的锁。这应该有你想要的效果。可悲的是,它仍然没有处理那些悬而未决的锁,但现在成为别人的问题。你的锁现在神奇地解锁。

static class LockProxy<L extends Lock> implements Lock { 

    // The actual lock. 
    private volatile Lock lock; 

    public LockProxy(L lock) { 
     // Trap the lock we are proxying. 
     this.lock = lock; 
    } 

    @Override 
    public void lock() { 
     // Proxy it. 
     lock.lock(); 
    } 

    @Override 
    public void lockInterruptibly() throws InterruptedException { 
     // Proxy it. 
     lock.lockInterruptibly(); 
    } 

    @Override 
    public boolean tryLock() { 
     // Proxy it. 
     return lock.tryLock(); 
    } 

    @Override 
    public boolean tryLock(long l, TimeUnit tu) throws InterruptedException { 
     // Proxy it. 
     return lock.tryLock(l, tu); 
    } 

    @Override 
    public void unlock() { 
     // Proxy it. 
     lock.unlock(); 
    } 

    @Override 
    public Condition newCondition() { 
     // Proxy it. 
     return lock.newCondition(); 
    } 

    // Extra functionality to unlock from any thread. 
    public void forceUnlock() { 
     // Actually just replace the perhaps locked lock with a new one. 
     // Kinda like a clone. I expect a neater way is around somewhere. 
     if (lock instanceof ReentrantLock) { 
      lock = new ReentrantLock(); 
     } else { 
      throw new UnsupportedOperationException(
       "Cannot force unlock of lock type " 
        + lock.getClass().getSimpleName()); 
     } 
    } 
} 
+0

是的,我被允许使用我自己的锁。谢谢! 我的伙伴和我实际上实现了我们自己的版本,它使用Semaphores来模拟LOCK接口 – 2013-05-15 16:34:18

+0

我看不到这个实现如何kes线正在等待上一个锁... – 2015-12-04 09:43:56

+0

@GerardoLastra - *可悲的是它仍然不处理留下的悬挂锁,但现在成为别人的问题。* – OldCurmudgeon 2015-12-04 10:02:30

10

你已经发现了一个重要的原因共同智慧说:不要杀线程!

锁只是强制杀死线程时可能发生的潜在资源泄漏之一。考虑打开的文件和套接字等。

还要考虑到,如果你确实设法解锁了锁,那么原因锁就是锁定在第一位。例如,线程可能已经部分更新了一个数据结构,并且允许从另一个线程访问该结构可能会导致奇怪且令人惊奇的程序故障,如果不是无法进行调试,则该故障很难。

处理这种情况的最好方法是要求线程消失。为与线程关联的对象添加一个“stop()”方法(每个线程都有一个对象,不是吗?),它会设置一个标志,并让线程定期检查该标志,并在设置时退出。

如果你的线程行为异常,阻止他们检查停止标志,那么正确的方法是修复代码,以免它行为不当。

-2

你为什么不干脆换你的线程的代码围绕以下:

ReentrantLock lock = ... obtain your lock somehow ... 
lock.lock(); 
try { 
    ... the "bad boy" code here ... 
} finally { 
    lock.unlock(); 
} 

然后,当你的线程结束(或者通过正常完成,或者从您的“杀”抛出一个异常) ,它会释放锁。

其实,这是Oracle建议使用的ReentrantLock方式:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html

+0

这并不能解决我的问题。你看,我有几个线程正在运行,并且解决方案就是当你可以知道锁属于谁时。真正的问题是我的LockManager必须在其他线程所拥有的锁上调用“unlock”=( – 2013-05-10 22:18:55

+0

)看起来你在使用该LockManager的一般体系结构时遇到了问题。在进行并发编程时,应该有一个“协作”心态:你的线程一起工作,而不是相互抵触,如果你想让LockManager调用unlock,或者你可以让你的LockManager提供,你可以使用完全相同的方法来替换lock.unalock()和lockManager.release(lock)你的工作者线程中会有一些用于通知线程的对象已经完成,并且完全按照上图所示使用它(即,{{}} finally {finishedFlag.set();} – 2013-05-11 05:59:49