2016-05-01 12 views
2

これは繰り返しの質問のようですが、はありませんONEセマフォを使用したインターネットでのReader Writerの問題Javaで。私が見つけた最も近いものはthisでしたが、セマフォを使用しないで答えとして答えが与えられています。Reader Writer probaをJavaで間違ったスレッド名で使用すると、同時に実行できず、同時実行ができなくなる

私はJavaでマルチスレッドに慣れていますので、私に同行してください。私のコードは次のとおりです。

import java.util.concurrent.Semaphore; 

class ReaderWritersProblem { 

    static Semaphore readLock = new Semaphore(1); 
    static Semaphore writeLock = new Semaphore(1); 
    static int readCount = 0; 

    static class Read implements Runnable { 
     @Override 
     public synchronized void run() { 
      try { 
       readLock.acquire(); 
       readCount++; 
       if (readCount == 1) { 
        writeLock.acquire(); 
       } 
       System.out.println("Thread "+Thread.currentThread().getName() + " is READING"); 
       Thread.sleep(1500); 
       System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING"); 
       readLock.release(); 
       readCount--; 
       if(readCount == 0) { 
        writeLock.release(); 
       } 
      } catch (InterruptedException e) { 
       System.out.println(e.getMessage()); 
      } 
     } 
    } 

    static class Write implements Runnable { 
     @Override 
     public synchronized void run() { 
      try { 
       writeLock.acquire(); 
       System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING"); 
       Thread.sleep(2500); 
       System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING"); 
       writeLock.release(); 
      } catch (InterruptedException e) { 
       System.out.println(e.getMessage()); 
      } 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     Read read = new Read(); 
     Write write = new Write(); 
     Thread t1 = new Thread(read); 
     t1.setName("thread1"); 
     Thread t2 = new Thread(read); 
     t2.setName("thread2"); 
     Thread t3 = new Thread(write); 
     t3.setName("thread2"); 
     Thread t4 = new Thread(read); 
     t4.setName("thread4"); 
     t1.run(); 
     t2.run(); 
     t3.run(); 
     t4.run(); 
    } 
} 

私は4つのスレッド、3つの読み込み用と1つの書き込み用に作成しています。スレッド主は
スレッド主は
スレッドを書き終えた
スレッド主 を読み終えた が
スレッド主に書き込んでメイン
スレッドを読み終えた
スレッドメインを読んで読んでいる

:のようなしかし、出力されますメインは READING
スレッドのメインは

返されるスレッド名は「メイン」で読み終えましたです。また、これらのすべては一見並行して実行されていません。どのように私はセマフォだけを使用してこのリーダーライター問題の実装を修正しますか? ReentrantReadLockなどを使用すると、これは簡単になりますが、セマフォを使用して問題を実装すると言う質問の目的を破ってしまいます。ありがとう

編集:また、HOW私は複数のスレッドの読書を表示しますか?私は実行結果を1つずつ取得しています。

EDIT:CORRECTED CODE:私はアルゴリズムを修正しました。これについていくつかのレビューをしたいと思います。

import java.util.concurrent.Semaphore; 

class ReaderWritersProblem { 

    static Semaphore readLock = new Semaphore(1); 
    static Semaphore writeLock = new Semaphore(1); 
    static int readCount = 0; 

    static class Read implements Runnable { 
     @Override 
     public void run() { 
      try { 
       //Acquire Section 
       readLock.acquire(); 
       readCount++; 
       if (readCount == 1) { 
        writeLock.acquire(); 
       } 
       readLock.release(); 

       //Reading section 
       System.out.println("Thread "+Thread.currentThread().getName() + " is READING"); 
       Thread.sleep(1500); 
       System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING"); 

       //Releasing section 
       readLock.acquire(); 
       readCount--; 
       if(readCount == 0) { 
        writeLock.release(); 
       } 
       readLock.release(); 
      } catch (InterruptedException e) { 
       System.out.println(e.getMessage()); 
      } 
     } 
    } 

    static class Write implements Runnable { 
     @Override 
     public void run() { 
      try { 
       writeLock.acquire(); 
       System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING"); 
       Thread.sleep(2500); 
       System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING"); 
       writeLock.release(); 
      } catch (InterruptedException e) { 
       System.out.println(e.getMessage()); 
      } 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     Read read = new Read(); 
     Write write = new Write(); 
     Thread t1 = new Thread(read); 
     t1.setName("thread1"); 
     Thread t2 = new Thread(read); 
     t2.setName("thread2"); 
     Thread t3 = new Thread(write); 
     t3.setName("thread3"); 
     Thread t4 = new Thread(read); 
     t4.setName("thread4"); 
     t1.start(); 
     t3.start(); 
     t2.start(); 
     t4.start(); 
    } 
} 

答えて

1

あなたの質問は、このコードが同時に実行されない理由と関連していると思います。これは、t1.run()メソッドではなくt1.start()メソッドを呼び出す必要があります(それに対応して、他のすべてのスレッドでも同様です)。 t1.run()はrun()メソッドをメインスレッドのコンテキストで実行し、新しいスレッドでは実行しません。

そして、すでにバイナリセマフォでコードを保護しているときに、同期化されたメソッドのポイントが表示されません。 2つのスレッドがバイナリセマフォを同時に取得することはできず、スレッドがセマフォを盲目的に解放しない限り、コードは安全です。これは、複数のリーダスレッドを持つことの恩恵を全滅させます。

コメントの新しい質問のために更新 - 複数のリーダースレッドが同じセクションにアクセスするようにする場合は、バイナリセマフォを使用するのではなく、より大きな値(好ましくはリーダースレッドの数に等しい)を使用してください。これらのスレッドはすべて、セマフォを取得し、完了したときに解放することができます。また、多くのリーダスレッドがアクティブなときにライタスレッドを飢えさせないように特別な注意を払わなければなりません。これは多くの方法で行うことができます - 読者のためだけにGoogle - ライターの問題とあなたはあなたがそれを行う方法を見つけるでしょう。

+0

これは、問題の一部を解決します。更新の質問を参照してください。同時スレッドの読み込みを出力するにはどうすればよいですか? – tsaebeht

+0

ありがとうございました。また、「スレッド2は読み込み、スレッド3は読み込み、スレッド2は読み込みを終了しました」などの出力をして、複数のスレッドが同時に読み込めることを示します。その場合、 'readLock'セマフォの上限を> 1に変更する必要がありますか?コードの残りの部分もOKですか? – tsaebeht

+0

私は答えを更新しました。しかし、私はまだ読者のスレッドでライターロックを取得しようとしているようなあなたのコードの部分を理解していません。だからあなたのコードに関する一般的なコメントを保持しています。 – Madhusudhan

関連する問題