2016-11-22 18 views
-1

私はキューを使用して基本的なセマフォ実装を作成しようとしています。アイデアは、データベースがあり、10人の作家がいるということです。ライターは、相互排除でのみデータベースに書き込むことができます。 First In First OutとLast In First Outを実装したいので、私はQueueを使用しています。キューを使用したセマフォの実装

セマフォを使用すると、特定のスレッドに起床するよう通知できません。だから私の考えは、私がやっているのはすべての作家のためです、私はオブジェクトを作成し、そのオブジェクトを待つように作家に伝えます。そのオブジェクトをキューに入れます。その後、キューからオブジェクトを削除し、そのオブジェクトを待機しているスレッドに通知します。このようにして、私はFIFOまたはLIFOの実装を行うことができると思います。

私は実際のコード実装について助けが必要です: 1.私は以下のコードを実行すると、私に多くのIllegalMonitorStateExceptionを与えました。 2. FIFOとLIFOコード(私のFIFOコードは正しくないようですが、LIFOコードの場合はQueueの代わりにStackを使用します)。

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

このコードと上記のコードとの違いは何ですか?私は 'wait()'の代わりに 'object.wait()'を使っています。なぜなら、そのオブジェクトを待ちたいから、待ち行列として使うことができるからです。私が 'wait()'を使用しているだけであれば、このセマフォーのインスタンスを待っていることを意味するわけではありませんし、 'notify()'を実行すると、特定のスレッドに目を覚ますことができません。 –

+0

コードを編集しました。 最初に、セマフォー・インスタンスがオブジェクトのインスタンスではなくロックされているため、IllegalMonitorStateExceptionがスローされます。 第2に、キューのサイズの代わりに状態整数が使用されて、動作中のスレッドが存在するかどうかを判断します。 キューのサイズが使用され、オブジェクトが追加された場合、スレッドは同じオブジェクトを削除してデッドロックになることがあります。 –

+0

ありがとう、これは私が必要とするものです。同期化されたメソッドではなく、取得と解放の同期化ブロックであることを詳細に説明できます –

関連する問題