Anzeige:
Ergebnis 1 bis 8 von 8

Thema: Threads und Read-Zugriff (J2ME)

  1. #1
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825

    Threads und Read-Zugriff (J2ME)

    Hallo Leute,

    habe hier 2 Threads laufen, die sich beim Lesen aus einer Datei (rm-store) ins Gehege kommen, einen eigenen und ein repaint().
    Beim Schreiben ist mir klar, warum. Aber wieso auch beim Lesen? (Gemeinerweise nur manchmal)

    Wer zu spät kommt, generiert einen Nullpointerexception. Das Programm selbst läuft mit allen (selbstangelegten) Threads ungestört weiter.

    Packe ich ein System.out.println("dingsbumsda"); dazwischen, sehe ich "das Gerangel", die Reihenolge der Indices der Leseschleife weisen auf 2 "parallele" Zugriffe hin. Aber durch die Zeitverzögerung ist das Lesen dann problemlos.

    Kann es sein, dass die Methoden, auch wenn sie keine Threads enthalten, im Gegensatz zu Javascript nicht atomar sind?
    Sind nicht mal die Schleifen atomar?

    System: Sun Java 1.6, Sun WTK 2.2

    Wat nu?
    Geändert von BlueJay (12-07-2007 um 13:59 Uhr)
    Eigentlich ganz einfach, wenn man's weiss!

  2. #2
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Du solltest selbst dafür sorgen, dass die Methoden die auf IO-Schnittstellen zugreifen, atomar sind.

    Versuchs aber einfach mal mit einem synchronize(file).
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  3. #3
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    Ich bin noch Java-Anfänger.
    Reicht es die public methods in der Class loadsave synchronized zu deklarieren?
    Eigentlich ganz einfach, wenn man's weiss!

  4. #4
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Nein, eigentlich meinte ich einen synchronized-Block. http://www.galileocomputing.de/openbook/javainsel6/javainsel_09_005.htm

    Also entweder mit dem alten:

    Code:
    File f = new File();
    
    synchronized(f){
     [irgendwas mit dem File machen]
    }
    oder die neue Methode mit lock und unlock setzen (seit Java 5).

    Aber wie gesagt, ist alles im obigen Link nachzulesen.

    lg, christian

    PS: Allgemein gilt, so wenig wie nötig synchronized setzen. Alle public-Methoden wäre also der falsche Weg.
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  5. #5
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    Die Publics dieser Klasse sind:

    Code:
    int get_int(int recId);
    String get_str(int recId);
    
    void set_int(int recId, int nr);
    void set_str(int recId, String text);
    und genau diese brauchen nur atomar zu sein.
    Datenlocation wird im Konstruktor übergeben.

    Mittlerweile habe ich eins der Objekte, die die Daten lesen, rausgeschmissen.

    Die J2ME-Bibilothek, bzw. das rms arbeitet nicht mit Lock und Konsorten zusammen (Beschreibung rms Sun) Ein util.concurrent suche ich da auch vergeblich. Derzeit behelfe ich mir so, dass es nur 1 Objekt gibt, was lesen/schreiben auslösen darf.

    Im von dir genannten Link steht (noch) dreist und frech, dass Read-Zugriffe durch verschiedene Threads unproblematisch seinen.

    Dem hat mittlerweile ein Professor in einer Vorlesung über Parallel Computing mit Java widersprochen und empfohlen, auch bei Read-Zugriffen zu locken.

    Nach meinen Erfahrungen (s.o.) mit J2ME (WTK 2.2) muss ich sagen, der Mann hat recht!
    (Link leider nicht zur Hand, war Vorlesungsscript-PDF)
    Eigentlich ganz einfach, wenn man's weiss!

  6. #6
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Wie gesagt, ich würde nur den Teil wo explizit auf das File zugegriffen wird, einen synchronized-Block drum-rum-setzen. Die ganze Methode synchronized zu setzen ist zwar auch eine Möglichkeit, aber irgendwie verwehre ich mich dagegen.

    Ich habe nur bis Java 1.6 gelesen und überlesen dass du J2ME verwendest.
    Hier solltest du auf die Methode mit synchronized-Block zurückgreifen. Damit habe ich im Bereich J2ME gute Erfahrungen gemacht.

    Dass man bei Read-Zugriffen locken sollte, kann man nicht verallgemeinern. Der Autor schreibt aber in diesem Bericht nur davon, dass wenn von Daten gelesen wird. Jedoch bei I/O-Operationen sieht das schon wieder ganz anders aus. Wenn z.B. das Filesystem konkurrierende Lesezugriffe (bei mobilen Geräten nicht unbedingt der Fall) nicht unterstützt, so sollte man hier locken. Wären aber bei Datenbanken keine konkurrierenden Lesezugriffe erlaubt und es wäre jede Leseoperation auf einen Datensatz oder eine Tabelle atomar, na dann Gute Nacht.
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  7. #7
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    Zitat Zitat von Waxolunist Beitrag anzeigen
    Wie gesagt, ich würde nur den Teil wo explizit auf das File zugegriffen wird, einen synchronized-Block drum-rum-setzen. Die ganze Methode synchronized zu setzen ist zwar auch eine Möglichkeit, aber irgendwie verwehre ich mich dagegen.
    Hier mal der schuldige Teil get_int, jetzige Version:
    Code:
    public synchronized int get_int(int id)
    {
       String t="0"; 
       if (open_read()) 
       {
          t=read_rs(id);
          close_rs();
       }
       return Integer.parseInt(t);
    }
    
    
     boolean open_read()
      { 
        try
       {
          rs=RecordStore.openRecordStore(rsdaten,false); // rsdaten ist global
        }
        catch (RecordStoreException ex) {  } 
        return (rs!=null);
      }
    
      void close_rs()
      { try 
        {
           if (rs != null) rs.closeRecordStore();
           rs=null;
        }
        catch (RecordStoreException ex) {  }
      }
    
      String read_rs(int idx)
      { int index=idx+1; // der rms faengt, warum auch immer, bei 1 an
        String zeile="";
        try
        {
          byte b[]=new byte[rs.getRecordSize(index)];
          int gelesen=rs.getRecord(index,b,0);
          if (gelesen>0) zeile=new String(b,0,gelesen);
        }
        catch (RecordStoreException ex) {  }
        return zeile;
      }
    Bei t.read_rs(id) griffen auf einmal 2 Threads zu (id gecheckt), bei close_rs() hat wohl der eine Thread dem anderen die Tür vor der Nase zugeknallt. Daten gab's trotzdem, weil nur ein Puffer damit refresht wurde, und es egal ist, wer liefert.
    Geändert von BlueJay (13-07-2007 um 15:13 Uhr)
    Eigentlich ganz einfach, wenn man's weiss!

  8. #8
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825

    rms, Problem mit der Recordlänge

    Tja, das Thema rms ist noch nicht um.

    ich pack's mal hierhin, weil da auch die Load/save Class schon zitiert ist.

    Folgendes Problem:
    Man löscht alles, was mit RecordStore zu tun hat, um den Handyzustand kurz nach dem Download zu emulieren.

    Und siehe da: ein ziemlich böser Effekt: bei einem der frisch angelegten RecordStore wird der 1. Wert "übersehen", d.h. er wird korrekt angelegt (wie alle seine Kollegen), ist aber später unter seiner Nummer nicht zugreifbar, und alle "gemeldeten" Indices scheinen um 1 verschoben.

    Die zu speichenden Daten beginnen mit 3 kurzen Records ( 1 - 4 bytes), dann folgen 2 Records a 81 Bytes.

    Beendet man die Anwendung und startet sie dann neu, läift alles korrekt ab, wenn man die Records zum 2. Mal anlegt.

    Auf dem (Motorola-)Handy scheint das gleiche Phänomen abzulaufen.

    Im rms sieht es auch nicht viel anders aus als beim 1.Mal, ausser, dass die beiden langen Records nun etwas tiefer stehen (so 32 bytes). Man sieht, dass da was umgeräumt wurde, aber es betraf nicht die ersten Records, sondern die beiden langen.

    Irgendwie scheint es mit den langen Records nach kurzen zusammenzuhängen, blende ich die beim Laden/Speichern aus, läuft alles glatt, auch beim 1.Mal.

    Irgendwelche Ideen dazu?
    Geändert von BlueJay (18-07-2007 um 20:54 Uhr)
    Eigentlich ganz einfach, wenn man's weiss!

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •