2013-05-10 58 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