2017-10-19 6 views
-1

で私自身のセマフォは、私はJavaで私自身のセマフォを実装したい 私はそのようにそれを実装している(ちょうど練習のために、私はセマフォクラスがあることを、認識しています)私は開始javaの

public class MyThread extends Thread { 

    private static MySemaphore semaphore = new MySemaphore(); 
    public void run(){ 
     for (int i = 0; i < 100; i++) { 

      semaphore.take(); 
      try { 
       Main.myVariable += 1; 
       semaphore.release(); 
      } catch (Exception e){ 
       System.out.println("Exception" + e.getMessage()); 
      } 
     } 
    } 
} 

と、このようにスレッドに参加:

import java.util.ArrayList; 
import java.util.List; 

public class Main { 

    public static int myVariable = 0; 

    private static int threadsNumber = 100; 

    public static void main(String[] args) { 
     List<Thread> allThreads = new ArrayList<>(); 

     for (int i = 0; i < threadsNumber; i++) { 
      allThreads.add(new Thread(new MyThread())); 
     } 

     for (int i = 0; i < threadsNumber; i++) { 
      allThreads.get(i).start(); 
     } 

     for (int i = 0; i < threadsNumber; i++) { 
      try{ 
       allThreads.get(i).join(); 
      } catch (Exception e){ 
       System.out.println(e.getMessage()); 
       System.out.println("********************************"); 
      } 
     } 

     System.out.println("Result is " + myVariable); 

    } 
} 

Iなどのスレッドでそれを使用しようとしています10000回変数をインクリメントして結果を受け取るだけです。セマフォなしでは、結果は10000未満(9923,9684など)です。これは、インクリメントの非アトミック性によって引き起こされます。私はセマフォを使ってこの変数を保護したい。
残念ながら、結果は依然として10000以下です(しかし、9990を超える9のケースでは、はるかに近くなります)。 なぜそれが起こるか考えていますか?私のセマフォーが間違っているのですか、スレッドを起動するのに何か問題がありますか?

+4

あなたが 'take'と混ぜ' release'を得たようです。 'take'(最初の操作)は待たなければならず、' release'は通知しなければなりません。 – JimmyB

+0

あなたは正しいです、メソッド名を入れ替えても機能しますが、私はちょうど良いメソッドを持っていましたが、間違った名前で(そしてそれに続くものは不適切に使用しました) – Dawid

+0

あなたは 'AtomicInteger'を使ってみましたか? – diginoise

答えて

-1

MySemaphoreクラスでは、値はすでに1に設定されています。リリース関数では、値がゼロに等しいかどうかを検証するため、値はゼロになります。これは、プログラムが起動したときにスレッドがセマフォを持つことができないことを意味します(1に設定しているためです)。そうすることで、彼らは待機状態になります。あなたのプログラムは、 'threadsNumber'が限界に達すると終了します。つまり、プログラムが終了する前にスレッドが待機状態にあるかどうかを確認していません。これはなぜあなたが成功率として9/10を持っているかを説明します。

私は、値をゼロに設定し、待機状態のスレッドがあるかどうかを確認することをお勧めします。

あなたのコードは、このようなこと:

public class MySemaphore { 
    private int value = 0; //this is already an error in your code 

    public synchronized void take() { 
    this.value++; 
    this.notify(); // wakes up the first thread that called wait on the shared variable 
    } 

    public synchronized void release() throws InterruptedException{ 
    while(this.signals == 0) wait(); 
    this.value--; 
    } 

} 
+1

'synchronized'ブロックの外側で' wait() '/' notify() 'を使ってみてください。結果を報告してください。 – lukeg

+1

セマフォーメソッドが行う操作はアトミックではないのでsynchronizedを使用しています。 – Dawid

+0

synchronizedキーワードを単純に使用できるときに、独自のセマフォを実装するポイントは何ですか? –