Thread Synchronisation

safin23

Grünschnabel
Hallo! Sitze seit Stunden an meinem Code und kriege es nicht hin
Meine Klasse RWMonitor soll zulassen, dass verschiedene Threads auf dasselbe Objekt gleichzeitig Lesesperren ( mode='r' halten können. Aber es ist verboten das gleichzeig zu der Lesesperre die Schreibsperre mod ='w' gehalten wird. Die Threads müssen sozusagen zerstückelt das Programm ablaufen...
Der Fehler liegt denke ich in der lock() bzw unlock() Methode. Aber bloss wo....
Die Trw Klasse erzeugt ein RWMonitor und 4 Threads. In der run() Mehtode soll mit zeitlicher Verzögerung jeweils die Schreibsperre bzw. Lesesperre gesetzt und freigegeben werden..
Wie gesagt, es dürfen viele lesen, ABER nicht lesen uns schreiben gleichzeitig...
Was mache ich falsch?
Hat jemand einen Tipp?

Code:
public class RWMonitor extends Thread implements Runnable {
	
	static char mode;
	static Integer anzahlLeseSperre = 0;
	static boolean schreibSperre = false;

	

	public static synchronized void lock(Thread t, char mode){
		
		//Setzen der Lesesperre
		if ( mode=='r')
		{
			if(schreibSperre == false)  {anzahlLeseSperre++;}}
				
				else{
					
					while(schreibSperre != false ){
						
						try{Thread.sleep(10);}
						catch( InterruptedException e)
						{System.out.println("Ein Fehler ist aufgetreten" + e);}	
						}
						anzahlLeseSperre++;}
						
		//Setzen der Schreibsperre	
		if( mode =='w')
			
			if(schreibSperre == false && anzahlLeseSperre == 0) {schreibSperre = true;}
		
				else{
				
					while(schreibSperre!= false && anzahlLeseSperre > 0){
						
						try{Thread.sleep(10); }
						catch( InterruptedException e)
						{System.out.println("Es ist ein Fehler aufgetreten" + e);}
					}
						schreibSperre = true;}
		}

	
	public static synchronized void unlock(Thread t, char mode){
		//Entsperren der Lesesperre
		if ( mode=='r')
			
			if(anzahlLeseSperre!=0)
				
				{anzahlLeseSperre--; schreibSperre = false;}
		//Entsperren der Schreibsperre	

		if( mode =='w')
			
			if(schreibSperre == true) schreibSperre = false;
		}	
}
Code:
import java.lang.Math;

public class Trw extends Thread {
	
	//RWMonitor mon;
	
	public static void main (String [] arg){
		
	//RWMonitor mon = new RWMonitor();	
	
	Trw t1 = new Trw();
	Trw t2 = new Trw();
	Trw t3 = new Trw();
	Trw t4 = new Trw();
	
	t1.start();
	t2.start();
	t3.start();
	t4.start();
	
	}
	
	public void run(){
		
		//int counter=0;
		char [] mode  = {'r','w'};
		
		for (int z = 0;z<5;z++){

		// Punkt 1.
			try{Thread.sleep((long)(Math.random()*50+1));}
				catch(InterruptedException e){
					System.out.println("Ein Fehler"+ e);}
		// Punkt 2.
		RWMonitor.mode = mode [(int)(Math.random()*2)];
		
		System.out.println(currentThread().getName()+ 
				" steht vor Eintritt  " + "Mode = "+ RWMonitor.mode+" "+RWMonitor.anzahlLeseSperre+RWMonitor.schreibSperre);
		
		RWMonitor.lock(currentThread(), RWMonitor.mode);
		
		System.out.println(currentThread().getName()+ 
				" hat betreten        " + "Mode = "+ RWMonitor.mode+" "+ RWMonitor.anzahlLeseSperre+RWMonitor.schreibSperre);
		
		    try{Thread.sleep((long)(Math.random()*50+1));}
			catch(InterruptedException e){
				System.out.println("Ein Fehler"+ e);}
		
		RWMonitor.unlock(currentThread(), RWMonitor.mode);
		
		System.out.println(currentThread().getName()+ 
				
				" steht vor Verlassen " + "Mode = "+ RWMonitor.mode+" "+RWMonitor.anzahlLeseSperre+RWMonitor.schreibSperre);

		
	}
	}	
	}
 
Zuletzt bearbeitet:
Wie wirkt sich dass aus dass du sagst dass es nicht geht?

Bau doch malnen paar Ausgaben ein die zeigen welcher Thread zu welchen Zeit was tut.
 
Thread-1 steht vor Eintritt Mode = w 0 false
Thread-1 hat betreten Mode = w 0 true
Thread-2 steht vor Eintritt Mode = r 0 true
Thread-3 steht vor Eintritt Mode = r 0 true
Thread-0 steht vor Eintritt Mode = w 0true

Zum Beispiel. Die Zahl bedeutet die Anzahl der Lesesperren. Ich denke das Problem liegt in der methode lock() bzw. unlock()... Aber ich komme trotzdem nicht dahinter...
 
Hebst du die sperren eigentlich überhaupt irgendwo wieder auf?

Mußt du das so programmieren oder könntest du auch die Locks der APIs verwenden?
 
Das ist ja das Problem :-( Unser Lehrer will nicht, dass wir wait() bzw notify() benutzen
D.h. wir müssen in unseren Funktionen lock() mit synchronized (this) {} arbeiten... Bloss ich weiss nicht genau, wo ich diese Synchronized Blöcke packen muss... Hier noch mal mein Code mit wait() und notify()
Code:
class RWMonitor3  { 

   int anzahlLeseSperre = 0; 
   boolean schreibSperre = false; 


   public synchronized void lock(Thread t, char mode) { 
      // Setzen der Lesesperre 
      if (mode == 'r') { 
         while (schreibSperre) { 
        	 try { 
                 wait(); 
        		// Thread.sleep(10); 
        		   		 
              } catch (InterruptedException e) { 
                 System.out.println("Ein Fehler ist aufgetreten" + e); 
              } 
           } 
           anzahlLeseSperre++; 
        } 

      // Setzen der Schreibsperre 
      if (mode == 'w') { 
         while (schreibSperre || anzahlLeseSperre > 0) { 
            try { 
             wait(); 
              
             // Thread.sleep(10); 
              
            } catch (InterruptedException e) { 
               System.out.println("Es ist ein Fehler aufgetreten" + e); 
            } 
         } 
         schreibSperre = true; 
      } 
   } 

   public synchronized void unlock(Thread t, char mode) { 
      // Entsperren der Lesesperre 
      if (mode == 'r') { 
         anzahlLeseSperre--; 
      } 
      // Entsperren der Schreibsperre 
      if (mode == 'w') { 
         schreibSperre = false; 
      } 
      notify(); 
   } 
}
Code:
public class Trw3 extends Thread { 

   static RWMonitor3 mon = new RWMonitor3(); 

   public static void main(String[] arg) { 

	  
      Trw3 t1 = new Trw3(); 
      Trw3 t2 = new Trw3(); 
      Trw3 t3 = new Trw3(); 
      Trw3 t4 = new Trw3(); 

      t1.start(); 
      t2.start(); 
      t3.start(); 
      t4.start(); 

   } 

   public void run() { 

    
      char[] mode = { 'r', 'w' }; 

      for (int z = 0; z < 5; z++) { 

         // Punkt 1. 
         try { 
            Thread.sleep((long) (Math.random() * 50 + 1)); 
         } catch (InterruptedException e) { 
            System.out.println("Ein Fehler" + e); 
         } 
         // Punkt 2. 
         char m = mode[(int) (Math.random() * 2)]; 

         System.out.println(currentThread().getName() + " steht vor Eintritt   " + "Mode = " + m 
               + " " + mon.anzahlLeseSperre + mon.schreibSperre); 

         mon.lock(currentThread(),m); 

         System.out.println(currentThread().getName() + " hat betreten         " + "Mode = " + m 
               + " " + mon.anzahlLeseSperre + mon.schreibSperre); 

         try { 
            Thread.sleep((long) (Math.random() * 500 + 1)); 
         } catch (InterruptedException e) { 
            System.out.println("Ein Fehler" + e); 
         } 

         System.out.println(currentThread().getName() + " steht vor  Verlassen " + "Mode = " + m 
               + " " + mon.anzahlLeseSperre + mon.schreibSperre); 

         mon.unlock(currentThread(),m); 

         System.out.println(currentThread().getName() + " steht nach Verlassen " + "Mode = " + m 
               + " " + mon.anzahlLeseSperre + mon.schreibSperre); 

      } 
   } 
}
 
Zurück