Message Queue mit einer Semaphore Klasse

nighty86

Grünschnabel
Hallo,

Ich brauch mal wieder eure Hilfe...
Ich muss hier eine Message Queue in Java basteln, jedoch mit einer selbst gebastelten Semaphore Klasse. Hier erstmal die Message Queue ohne Semaphore, d.h die "normale" :

Java:
package fopt.assignment2a;



public class Buffer 
{
	private boolean available = false;
	private int data;
	//private Semaphore[] sems;
	
	public synchronized void put( int x)
	{
		while(available)
		{
			try
			{
				wait();
			}
			catch(InterruptedException e)
			{
				
			}			
		}
		data = x;
		available = true;
		notifyAll();
	}
	
	public synchronized int get()
	{
		while(!available)
		{
			try
			{
				wait();
			}
			catch(InterruptedException e)
			{
				
			}
		}
		available = false;
		notifyAll();
		return data;
	}

}


Die funktioniert auch ohne Probleme, die wird im System auch richtig bewertet!

Jetzt meine Semaphore Klasse :

Java:
package fopt.assignment2b;

public class Semaphore 
{
	private int value;
	
	public Semaphore(int init)
	{
		if(init < 0)
		{
			init = 0;
		}
		value = init;
	}
	
	public synchronized void p()
	{
		while(value==0)
		{
			try
			{
				wait();
			}
			catch(InterruptedException e)
			{
				
			}
		}
		value--;
	}

	public synchronized void v()
	{
		value++;
		notify();
	}
}

Die ist denk ich (?) auch richtig so!


Jetzt die Message Queue mit den Semaphoren :

Java:
package fopt.assignment2b;

public class Buffer 
{
    private Semaphore sem1;
    private Semaphore sem2;
    private int[] data = null;
    private int tail;
    private int head;
    private int numberOfElements;
    
    public Buffer(int n)
    {
        if (n <= 0) 
        {
            throw new IllegalArgumentException();
        }
        data = new int[n];
        tail = 0;
        head = 0;
        numberOfElements = 0;
        sem1 = new Semaphore(1);
        sem2 = new Semaphore(0);
        
    }
    
    public void put(int x) 
    {
        while (numberOfElements == data.length) 
        {
            sem2.p();
        }
        sem1.p();

        data[tail++] = x;
        if (tail == data.length) 
        {
            tail = 0;
        }
        numberOfElements++;
      
        sem1.v();
        sem2.v();
       }

    public int get() 
    {

        while (numberOfElements == 0) 
        {
            sem2.p();
        }
        
        sem1.p();
        int result = data[head++];
        if (head == data.length) 
        {
            head = 0;
        }
        numberOfElements--;
        
        sem1.v();
        sem2.v();
        return result;
        

    }

}

Die funktioniert aber nicht ****
Vor allem meckert das System, dass ich eben die Semaphore nicht richtig benutze. Aber, ich brauch doch jeweils einen für den gegenseitigen Ausschluss der Methoden, sowie einen für den Produzenten und Konsumenten. Das müsste doch auch so stimmen, oder nicht?
 
Du möchstest dass get und put unabhängig voneinander verwendet werden können? Weil sonst reicht doch eine Semaphore?

Deine erste Buffer Klasse ist auch sehr anders, da sie nur ein Element enthält.

Bitte eine InterruptedException nicht ignorieren. Ein Interrupt ist eine Möglichkeit einen Thread zu beenden. Das richtigen Verhalten in deinem Fall ist den interrupted-Status des Thread wieder zu setzen damit dieser nicht verloren geht: Thread.currentThread().interrupt() und dann aus der Methode zu returnen oder wenn möglich eine geeignete Exception zu werfen um anzuzeigen dass die Aktion fehlgeschlagen ist.
 
Hallo,
Danke erstmal für deine Hilfe!
Im Grunde will ich das synchronized durch semaphore ersetzen! Sprich, ein gegenseitigen Ausschluss.
Als Fehlermeldung krieg ich folgendes :

Vermutlich wurde mehr als ein Semaphor für den gegenseitigen Ausschluß verwendet, sind Sie sicher das der gegenseitige Auschluß konsistent über die selbe Semaphor realisiert wurde?

Ich brauche aber zwei Semaphore, weil ich ja eben auch einen brauche für den Fall dass die queue voll ist, oder eben leer ist (while-Schleife).

Was das Interrupt vom Thread angeht, da muss ich ehrlich zugeben : Soweit sind wir noch nicht im Kurs ;-) B.z.w hab ich grad kein Plan was ich damit genau anfangen soll.

/edit/
Also, die Fehlermeldung kommt, wenn ich 3 Semaphore nutze :

Java:
package fopt.assignment2b;
 
public class Buffer 
{
    private Semaphore sem1;
    private Semaphore sem2;
    private Semaphore sem3;
    private int[] data = null;
    private int tail;
    private int head;
    private int numberOfElements;
    
    public Buffer(int n)
    {
        if (n <= 0) 
        {
            throw new IllegalArgumentException();
        }
        data = new int[n];
        tail = 0;
        head = 0;
        numberOfElements = 0;
        sem1 = new Semaphore(1);
        sem2 = new Semaphore(0);
        sem3 = new Semaphore(1);
        
    }
    
    public void put(int x) 
    {
        while (numberOfElements == data.length) 
        {
            sem2.p();
        }
        sem1.p();
 
        data[tail++] = x;
        if (tail == data.length) 
        {
            tail = 0;
        }
        numberOfElements++;
      
        sem1.v();
        sem3.v();
        
       }
 
    public int get() 
    {
 
        while (numberOfElements == 0) 
        {
            sem3.p();
        }
        
        sem1.p();
        int result = data[head++];
        if (head == data.length) 
        {
            head = 0;
        }
        numberOfElements--;
        
        sem1.v();
        sem2.v();
        return result;
        
 
    }
 
}
 
Zuletzt bearbeitet:
Du brauchst nur eine Semaphore, weil sich die Operationen gegenseitig ausschließen sollen. Im Grund ersetzt deine Semaphore das synchronized Schlüsselwort, nur dass du die zu schützend Bereich nicht auf die ganze Methode ausdehnen mußt, sondern nur genau so groß wie sie sein müssen. Das synchronized sorgt ja dafür, dass jeweils nur die eine oder andere Methode betreten werden darf, aber nie beide gleichzeitig von verschiedenen Threads.

Klingt nach einem interessanten System was ihr da habt :)

Ums mal zu versuchen zu erklären: Wenn man ein Objekt hat, was von mehreren Threads zugegriffen wird, muss man natürlich schauen, dass nicht zwei Threads gleichzeitig den selben Wert verändern können, sondern sich eben abwechseln. Dafür kann man dann die Codeabschnitte so absichern, dass nicht zwei Threads gleichzeitig darauf zugreifen können.

Zu der InterruptedException: In Java kann man einen Thread nur durch einen Interrupt beenden/abbrechen. Damit ein Thread nicht einfach während einer wichtigen Aufgabe unterbrochen wird, passiert dieses nur an dafür vorgesehenen stellen, z.B. wenn der Thread gerade nichts tut, also wie in deinem Fall im wait() ist. Damit der Thread abgebrochen wird, mußt du natürlich dies auch akzeptieren und damit geeignet auf einen solche Abbruch reagieren.

Aber solang du noch nicht weißt was du mit einer Exception anfängst, logge sie zumindest auf jeden Fall zumindest auf die Konsole!
 
Alsooooo,
Sorry erstmal falls ich so wirke, als wär ich schwer von Begriff! ;)

Ich brauche nur 1 Semaphore? D.h ich nutze den gleichen Semaphore einerseits für get und put als Methode insgesamt? (synchronized)
Aber, ich muss ja auch den Thread zum warten kriegen, falls zum Beispiel meine Queue voll oder leer ist? (wait, notify...). Vor allem dort liegt, denk ich, mein Problem! Oder ich liege komplett falsch :-(


Das System ist an sich ganz toll. Nennen sie bei uns (FH Trier..) "ASB", automatische software bewertung. Wir kriegen da regelmäßig "Hausaufgaben", und die werden dort eben bewertet ;)


Danke auch für deine Erklärung was die Exception angeht!
 
Die Semaphore ersetzt nur die Synchronisierung, der Rest bleibt gleich. Das wait und notify funktioniert noch genauso :)

Versuche bei Programmierung mit Threads immer sehr ordentlich und genau zu arbeiten. Leider gibt es keine "Versicherung", dass dein Programm korrekt es nur weil es bei dir das richtige tut.
 
Das Problem ist ja, die Aufgabenstellung ist so :

Sie dürfen aber außer in dieser Semaphorklasse in Ihrem Programm an keiner anderen Stelle synchronized, wait, notify und notifyAll verwenden

Also, ich muss eben wait und notify durch einen Semaphore ersetzen.

Hier auch die ASB Meldung jetzt :
Test Semaphoren Vermutlich falsche Verwendung der Semaphore. Es muss ein Semaphor für den gegenseitigen Ausschluß, sowie ein Semaphor für den Produzenten und Konsumenten vorhanden sein
 
Zuletzt bearbeitet:
Es steht dir aber frei sonstige Bedingungen zu verwenden ;)

Mehr möchte ich da gerade nicht zu sagen, du sollst schon selber drauf kommen. Schau einfach mal ob dus mit einer hinbekommst. Wenn's heute nicht mehr klappt, schlaf ne Nacht drüber, das hilft manchmal tatsächlich.
 
jetzt erst gesehen, sorry, ich hab da die falsche erste Bufferklasse hier reinkopiert. Natürlich hat die auch ein Feld, also nicht nur ein Element!

Java:
package fopt.assignment2a;

public class Buffer 
{
    private int[] data = null;
    private int tail;
    private int head;
    private int numberOfElements;

    public Buffer(int n) 
    {
        if (n <= 0) 
        {
            throw new IllegalArgumentException();
        }
        data = new int[n];
        tail = 0;
        head = 0;
        numberOfElements = 0;
    }

    public synchronized void put(int x) 
    {

        while (numberOfElements == data.length) 
        {
            try 
            {
                wait();
            } 
            catch (InterruptedException e) 
            {
            }
        }
        data[tail++] = x;
        if (tail == data.length) 
        {
            tail = 0;
        }
        numberOfElements++;
        notifyAll();
    }

    public synchronized int get() 
    {
        while (numberOfElements == 0) 
        {
            try 
            {
                wait();
            } 
            catch (InterruptedException e) 
            {
            }
        }
        int result = data[head++];
        if (head == data.length) 
        {
            head = 0;
        }
        numberOfElements--;
        notifyAll();
        return result;

    }

}
Das ist die Richtige. Die Vorherige war eine Aufgabe "vorher" ;-)

Zum Rest, danke erstmal. Ich grüble mal weiter! ;)
 

Neue Beiträge

Zurück