2016-02-09 108 views
2

我需要優先構建我所謂的「不公平信號」。 例如:當一個線程與priority = 1想要獲得信號量,它只需要等到具有相同優先級的其他線程完成,那麼它可以acquire()。但是當priority = 2的線程想要獲取信號量時,它必須等待所有使用priority = 1的線程在使用信號量之前完成,然後嘗試acquire()。 我總共有4個不同的優先級。 這是我試過的,但沒有奏效。互斥優先於JAVA

有人有任何解決方案嗎?

public class UnfairSemaphore 
{ 
    private Semaphore mPrior1; 
    private Semaphore mPrior2; 
    private Semaphore mPrior3; 
    private Semaphore mPrior4; 

    public UnfairSemaphore() 
    { 
     mPrior1 = new Semaphore(1); 
     mPrior2 = new Semaphore(1); 
     mPrior3 = new Semaphore(1); 
     mPrior4 = new Semaphore(1); 
    } 

    public void acquire(int priority) throws InterruptedException 
    { 
     if(priority == 1) 
     { 
      mPrior1.acquire(); 
     } 
     else if(priority == 2) 
     { 
      while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0) 
      { 
       //wait(); 
      } 
      mPrior2.acquire(); 
      mPrior1.acquire(); 
     } 
     else if(priority == 3) 
     { 
      while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0 && mPrior2.hasQueuedThreads() && mPrior2.availablePermits() <=0) 
      { 
       //wait(); 
      } 
      mPrior3.acquire(); 
      mPrior2.acquire(); 
      mPrior1.acquire(); 
     } 
     else 
     { 
      while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0 && mPrior2.hasQueuedThreads() && mPrior2.availablePermits() <=0 && mPrior3.hasQueuedThreads() && mPrior3.availablePermits() <=0) 
      { 
       //wait(); 
      } 
      mPrior4.acquire(); 
      mPrior3.acquire(); 
      mPrior2.acquire(); 
      mPrior1.acquire(); 
     } 
    } 

    public void release(int priority) 
    { 
     if(priority == 1) 
     { 
      mPrior1.release(); 
     } 
     else if(priority == 2) 
     {   
      mPrior1.release(); 
      mPrior2.release();   
     } 
     else if(priority == 3) 
     {   
      mPrior1.release(); 
      mPrior2.release(); 
      mPrior3.release(); 
     } 
     else 
     {   
      mPrior1.release(); 
      mPrior2.release(); 
      mPrior3.release(); 
      mPrior4.release(); 
     } 
     //notifyAll(); 
    } 
} 
+4

「但它沒有奏效」它做了什麼呢? –

回答

-1

爲什麼要自己管理線程?

您應該使用Thread類中的synchronised關鍵字和setPriority方法。

請看下面的鏈接:

https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#setPriority%28int%29

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

+0

可能是很好的建議,但標準版Java中的「優先級」沒有多大意義。如果OP需要確定某些事情的真正優先級(即,應用程序是否有嚴格的實時要求),那麼它應該在實時Java平臺上運行。 –

+0

線程優先級不會做你認爲他們正在做的事情。地獄同步不是一個公平的鎖(開始的時候是不錯的選擇,公平的鎖是可怕的表現) – Voo

+0

問題是優先級不取決於Thead,而是取決於「線程需要訪問資源的地方」。然後,有時候,優先級會降低,有時候會更高。 – Vanpourix

0

的基本要求是,我們有一堆等待線程,每個線程優先級的。在release()上,我們選擇一個優先級最高的等待線程,並將其喚醒。

這可以通過LockSupport中的線程park()unpark()完成。它是一種低級併發工具,但我們不會將它用於精英;我們使用它是因爲它最自然地模擬我們的解決方案

首先我們需要一個數據結構來存儲等待線程及其優先級。你可以用很多方式來做到這一點。

void storeWaitingThread(Integer priority, Thread thread) { ... } 

    // select and remove a waiting thread with highest priority; return null if none. 
    Thread selectWaitingThread(){ ... } 

現在,release()只會選擇一個等待的線程和unpark

final Object lock = new Object(); 

volatile Thread owningThread; 

public void release() 
{ 
    synchronized (lock) 
    { 
     Thread nextOwner = selectWaitingThread(); 
     owningThread = nextOwner; 
    } 
    LockSupport.unpark(owningThread); 
} 

acquire(priority)將存儲在當前線程的等待線程;公園,直到它被選中

public void acquire(int priority) 
{ 
    Thread thisThread = Thread.currentThread(); 
    synchronized (lock) 
    { 
     if(owningThread==null) 
     { 
      owningThread=thisThread; 
      return; 
     } 
     storeWaitingThread(priority, thisThread); 
    } 

    while(owningThread!=thisThread) 
    { 
     LockSupport.park(); 
     // interrupt ignored. // todo handle interrupt 
    } 
} 

查看完整的代碼在https://gist.github.com/zhong-j-yu/3ea91194f55d91059789

注意,我們acquire會忽略中斷。如果它應該保留在中斷上,請在park()醒來後添加一些邏輯。

+0

我沒有測試過它:)親自試一試,看看它是否有效。 – ZhongYu