2017-10-19 4 views
-1

Ich mag würde meine eigene Semaphore in Java implementieren (nur für die Praxis, ich bin mir dessen bewusst, dass es Semaphore-Klasse) ich es so umgesetzt haben:Meine eigene Semaphore in Java

public class MySemaphore { 
    private int value = 1; 


    public synchronized void take() { 
     this.value++; 

     this.notify(); 
    } 

    public synchronized void release(){ 


     while (this.value == 0) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
      } 
     } 

     this.value--; 
    } 

} 

I ich versuche es in einer solchen Thread zu verwenden:

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()); 
      } 
     } 
    } 
} 

ich anfangen und Themen wie folgt verbinden:

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 will nur eine Variable 10000 mal erhöhen und ein Ergebnis erhalten. Ohne Semaphor beträgt das Ergebnis weniger als 10000 (wie 9923, 9684), was durch Nichtatomizität der Inkrementierung verursacht wird. Ich möchte diese Variable mit Semaphor schützen.
Leider ist das Ergebnis immer noch weniger als oder gleich 10000 (aber viel näher, in 9 von 10 Fällen größer als 9990). Haben Sie eine Idee, warum es passiert? Ist mein Semaphor falsch oder mache ich etwas falsch beim Starten von Threads?

+4

Es scheint, dass Sie das 'take' bekam und' release' gemischt. 'take' (erste Operation) muss warten,' release' muss benachrichtigt werden. – JimmyB

+0

Sie haben Recht, ich tauschte Methodennamen und das funktioniert, ich hatte nur gute Methoden, aber mit falschen Namen (und was folgt, habe ich sie falsch verwendet), danke. – Dawid

+0

haben Sie versucht, 'AtomicInteger' zu verwenden? – diginoise

Antwort

-1

In Ihrer MySemaphore-Klasse ist der Wert bereits auf 1 gesetzt. Er sollte null sein, da Sie in Ihrer Freigabefunktion überprüfen, ob der Wert gleich Null ist oder nicht. Das bedeutet, dass beim Start Ihres Programms kein Thread den Semaphor haben kann (weil Sie ihn auf 1 gesetzt haben); dabei fallen sie in einen Wartezustand. Ihr Programm endet, wenn 'stringsNumber' das Limit erreicht. Mit anderen Worten, Sie überprüfen nicht, ob sich ein Thread im Wartezustand befindet, bevor die Programme enden. Dies erklärt, warum Sie eine Erfolgsquote von 9/10 haben.

Meine Empfehlung wäre, den Wert auf Null zu setzen und zu überprüfen, ob Threads im Wartezustand sind.

Ihr Code wie folgt sein:

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

Versuchen Sie 'wait()'/'notify()' außerhalb des 'synchronisierten' Blocks zu verwenden. Melden Sie die Ergebnisse. – lukeg

+1

Ich verwende synchronisiert, weil Operationen, die Semaphor-Methoden tun, nicht atomar sind, möchte ich sie so machen. – Dawid

+0

Was ist der Punkt, um einen eigenen Semaphor zu implementieren, wenn Sie einfach das synchronisierte Schlüsselwort verwenden können. –