2016-11-22 89 views
-1

我想創建一個基本的信號量實現使用隊列。這個想法是,有一個數據庫,有10個作家。作者只能相互排斥地寫入數據庫。我使用Queue是因爲我想實施先進先出和後進先出。實現一個隊列的信號量

使用信號燈,我無法通知特定的線程來喚醒。所以我的想法就是我爲每個Writer創建一個對象並告訴Writer等待這個對象。將該對象放入隊列中。然後從隊列中刪除對象並通知正在等待該對象的線程。通過這種方式,我認爲我可以實現FIFO或LIFO實施。

我需要幫助的實際代碼執行: 1.我運行下面的代碼,它給了我很多IllegalMonitorStateException。 2. FIFO和LIFO代碼(我的FIFO代碼看起來不正確,而對於LIFO代碼,我想用堆棧代替隊列)。

public class Test { 
    public static void main(String [] args) { 
    Database db = new Database(); 

    for (int i = 0; i < 10; i++) 
     (new Thread(new Writer(db))).start(); 
    } 
} 

public class Writer implements Runnable { 

    private Database database; 

    public Writer(Database database) { 
    this.database = database; 
    } 

    public void run() { 
    this.database.acquireWriteLock(); 

    this.database.write(); 

    this.database.releaseWriteLock(); 
    } 
} 

public class Database { 

    private Semaphore lockQueue; 

    public Database() { 
    this.lockQueue = new Semaphore(); 
    } 

    public void write() { 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException ie) {} 
    } 

    public void acquireWriteLock() { 
    lockQueue.acquire(); 
    } 

    public void releaseWriteLock() { 
    lockQueue.release(); 
    } 
} 

import java.util.Queue; 
import java.util.LinkedList; 

public class Semaphore { 
    private Queue<Object> queue; 

    public Semaphore() { 
    this.queue = new LinkedList<Object>(); 
    } 

    public synchronized void acquire() { 
    Object object = new Object(); 

    try { 
     if (this.queue.size() > 0) { 
     object.wait(); 
     this.queue.add(object); 
     } 
    } catch (InterruptedException ie) {} 

    this.queue.add(object); 
    } 

    public synchronized void release() { 
    Object object = this.queue.remove(); 
    object.notify(); 
    } 
} 

回答

1

在使用wait()和notify()之前,您需要獲取對象的鎖定。 試着檢查下面的代碼是否可以工作:

public class Semaphore { 
    private Queue<Object> queue; 
    private int state; 

    public Semaphore() { 
     this.queue = new LinkedList<Object>(); 
    } 

    public void acquire() { 
     Object object = new Object(); 

     synchronized (object) { 
      try { 
       if (this.state > 0) { 
        this.queue.add(object); 
        object.wait();     
       } else { 
        state++; 
       } 

      } catch (InterruptedException ie) { 
      } 

     } 
    } 

    public void release() { 
     Object object = this.queue.poll(); 

     state--; 

     if(null == object) { 
      return; 
     } 

     synchronized (object) { 
      object.notify(); 
     } 
    } 
} 
+0

這段代碼和我上面寫的代碼有什麼區別?我使用'object.wait()'而不是'wait()',因爲我想等待那個對象,所以我可以用它作爲隊列。如果我只是使用'wait()',這不就意味着我在等待這個Semaphore實例,並且當我做'notify()'時,我無法通知特定的線程喚醒 –

+0

我編輯了代碼基於以下原因: 1,由於Semaphore實例被鎖定而不是對象的實例,所以引發IllegalMonitorStateException。 第二,使用狀態整數而不是隊列的大小來確定是否有工作線程。 如果使用隊列大小並添加對象,則線程可能會刪除同一對象,從而導致死鎖。 –

+0

謝謝,這正是我需要的。你能詳細說明爲什麼它是一個獲取和釋放的同步塊而不是同步方法嗎? –