kramann.info
© Guido Kramann

Login: Passwort:










5.2 Darstellung des Synchronisierungsvorgangs von Lese- und Schreibprozessen mit Java

java_semaphor.zip - Download der nachfolgenden Java-Projekte.
  • Der für die drei Mikrocontroller A,B und C beschriebene Synchronisierungsmechanismus läßt sich auch in einem Java-Programm mit drei Threads darstellen.
  • Dabei gibt es statt der Datenleitungen zwei Arrays: arrA wird von A beschrieben und von C gelesen. arrB wird von B geschrieben und von C gelesen.
  • In arrA und arrB wird immer abwechselnd das ganze Array mit Nullen und beim nächsten Schreibzyklus mit Einsen gefüllt.
  • Sollte der Lesevorgang stattfinden, wenn der Schreibvorgang noch nicht abgeschlossen ist, so sind nicht alle Arrayzellen in gleicher Weise gefüllt (entweder nur Nullen oder nur Einsen).
  • Dies passiert, wenn die Zugriffe auf die Arrays unkontrolliert stattfinden.
  • Zunächst soll dies demonstriert werden:
public class SchreibenA extends Thread
{
    public boolean einser = false;
    public void run()
    {
        while(true)
        {
            for(int i=0;i<30;i++)
            {
                if(einser)
                    Hauptprogramm.arrA[i]=1;
                else
                    Hauptprogramm.arrA[i]=0;
                Hauptprogramm.pausieren(20);
            }
            //Erledige andere Aufgaben:
            Hauptprogramm.pausieren(50);
            einser = !einser;
        }
    }
}

Code 5.2-1: SchreibenA.java in Projekt 001_unkontrolliert

public class SchreibenB extends Thread
{
    public boolean einser = false;
    public void run()
    {
        while(true)
        {
            for(int i=0;i<30;i++)
            {
                if(einser)
                    Hauptprogramm.arrB[i]=1;
                else
                    Hauptprogramm.arrB[i]=0;
                Hauptprogramm.pausieren(20);
            }
            //Erledige andere Aufgaben:
            Hauptprogramm.pausieren(50);
            einser = !einser;
        }
    }
}

Code 5.2-2: SchreibenB.java in Projekt 001_unkontrolliert

public class LesenC extends Thread
{
    public void run()
    {
        while(true)
        {
            System.out.println("C  liest nun arrA aus:");
            for(int i=0;i<30;i++)
            {
                System.out.print(Hauptprogramm.arrA[i]);
                Hauptprogramm.pausieren(100);
            }
            System.out.println();
            System.out.println("C  liest nun arrB aus:");
            for(int i=0;i<30;i++)
            {
                System.out.print(Hauptprogramm.arrB[i]);
                Hauptprogramm.pausieren(100);
            }
            System.out.println();
            //Erledige andere Aufgaben:
            Hauptprogramm.pausieren(200);
        }
    }
}

Code 5.2-3: LesenC.java in Projekt 001_unkontrolliert

public class Hauptprogramm
{
    public static int[] arrA={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    public static int[] arrB={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    public static void pausieren(long ms)
    {
        try
        {
            Thread.sleep(ms);
        }
        catch(Exception e)
        {
        }
    }
    public static void main(String[] args)
    {
        SchreibenA schreibenA = new SchreibenA();
        SchreibenB schreibenB = new SchreibenB();
        LesenC lesenC = new LesenC();
        schreibenA.start();
        schreibenB.start();
        lesenC.start();
        pausieren(20000);
        while(lesenC==Thread.currentThread());        
        lesenC.stop();
        while(schreibenB==Thread.currentThread());        
        schreibenB.stop();
        while(schreibenA==Thread.currentThread());        
        schreibenA.stop();
    }
}

Code 5.2-4: Hauptprogramm.java in Projekt 001_unkontrolliert

  • In der Konsole erscheint nach Start des Programmes:
C  liest nun arrA aus:
000000000111111110000000011111
C  liest nun arrB aus:
000011111111000000001111111100
C  liest nun arrA aus:
111110000000011111111000000001
C  liest nun arrB aus:
000000001111111100000000111111
C  liest nun arrA aus:
011111111000000001111111100000
C  liest nun arrB aus:
111100000000111111110000000011

Code 5.2-5: Konsolenausgabe

  • Die Arrays sind somit nicht sauber zuende geschrieben worden, als die Zugriffe auf diese erfolgten.
  • Nun wird der gegenseitige Sperrmechanismus mit Hilfe boolscher Variablen ähnlich wie bei den Mikrocontrollern realisiert:
public class SchreibenA extends Thread
{
    public boolean einser = false;
    public void run()
    {
        while(true)
        {
          if(Hauptprogramm.CliestA==false)
          {
            Hauptprogramm.Aschreibt=true;
            for(int i=0;i<30;i++)
            {
                if(einser)
                    Hauptprogramm.arrA[i]=1;
                else
                    Hauptprogramm.arrA[i]=0;
                Hauptprogramm.pausieren(20);
            }
            Hauptprogramm.Aschreibt=false;
            einser = !einser;
          } 
          //Erledige andere Aufgaben:
          Hauptprogramm.pausieren(50);
        }
    }
}

Code 5.2-6: SchreibenA.java in Projekt 002_kontrolliert

public class SchreibenB extends Thread
{
    public boolean einser = false;
    public void run()
    {
        while(true)
        {
          if(Hauptprogramm.CliestB==false)
          {
            Hauptprogramm.Bschreibt=true;
            for(int i=0;i<30;i++)
            {
                if(einser)
                    Hauptprogramm.arrB[i]=1;
                else
                    Hauptprogramm.arrB[i]=0;
                Hauptprogramm.pausieren(20);
            }
            Hauptprogramm.Bschreibt=false;
            einser = !einser;
          } 
          //Erledige andere Aufgaben:
          Hauptprogramm.pausieren(50);
        }
    }
}

Code 5.2-7: SchreibenB.java in Projekt 002_kontrolliert

public class LesenC extends Thread
{
    public void run()
    {
        while(true)
        {
          if(Hauptprogramm.Aschreibt==false)
          {
            Hauptprogramm.CliestA=true;
            System.out.println("C  liest nun arrA aus:");
            for(int i=0;i<30;i++)
            {
                System.out.print(Hauptprogramm.arrA[i]);
                Hauptprogramm.pausieren(100);
            }
            System.out.println();
            Hauptprogramm.CliestA=false;
          }
          if(Hauptprogramm.Bschreibt==false)
          {
            Hauptprogramm.CliestB=true;
            System.out.println("C  liest nun arrB aus:");
            for(int i=0;i<30;i++)
            {
                System.out.print(Hauptprogramm.arrB[i]);
                Hauptprogramm.pausieren(100);
            }
            System.out.println();
            Hauptprogramm.CliestB=false;
          }
          //Erledige andere Aufgaben:
          Hauptprogramm.pausieren(200);
        }
    }
}

Code 5.2-8: LesenC.java in Projekt 002_kontrolliert

public class Hauptprogramm
{
    public static int[] arrA={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    public static int[] arrB={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    public static boolean Aschreibt = false;
    public static boolean Bschreibt = false;
    public static boolean CliestA   = false;
    public static boolean CliestB   = false;
    public static void pausieren(long ms)
    {
        try
        {
            Thread.sleep(ms);
        }
        catch(Exception e)
        {
        }
    }
    public static void main(String[] args)
    {
        SchreibenA schreibenA = new SchreibenA();
        SchreibenB schreibenB = new SchreibenB();
        LesenC lesenC = new LesenC();
        schreibenA.start();
        schreibenB.start();
        lesenC.start();
        pausieren(30000);
        while(lesenC==Thread.currentThread());        
        lesenC.stop();
        while(schreibenB==Thread.currentThread());        
        schreibenB.stop();
        while(schreibenA==Thread.currentThread());        
        schreibenA.stop();
    }
}

Code 5.2-9: Hauptprogramm.java in Projekt 001_unkontrolliert

C  liest nun arrA aus:
111111111111111111111111111111
C  liest nun arrB aus:
111111111111111111111111111111
C  liest nun arrA aus:
000000000000000000000000000000
C  liest nun arrB aus:
000000000000000000000000000000

Code 5.2-10: Konsolenausgabe

  • Nun tritt der Fall nicht mehr auf, dass die Arrays ausgelesen werden, wenn sie nicht fertig beschrieben wurden.
  • Allerdings läuft das Programm nun auch langsamer.