tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
9
ZUGRIFFE
360
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    chickenwings chickenwings ist offline Mitglied Gold
    Registriert seit
    Nov 2005
    Beiträge
    213
    Hallo,

    ich suche derzeit intensiv nach einer Möglichkeit des exklusiven Zugriffs auf ein Objekt innerhalb einer Map.

    Es soll also n Threads geben, die auf eine Map zugreifen. In dieser Map sind bestimmte Objekte enthalten. Wenn nun ein Thread sich ein Objekt herausholt, um es zu bearbeiten, soll explizit dieses Objekt für den Zugriff durch andere Threads gesperrt werden.

    Ich bin mir allerdings noch nicht sicher, wie ich das steuern soll, ob es da evtl. schon Java Hausmittelchen gibt. Meine bisherige Idee wäre, dass der Thread, der sich das Objekt zum Lesen herausholt, in eine zweite Map ablegt, die nur Objekte beinhaltet, die gerade bearbeitet werden. So könnte ein anderer Thread dort nachsehen, ob es schreibbar ist oder nicht.

    Hat jemand schon mal ein ähnliches Problem gelöst?

    Grüsse,
    chickenwings
     

  2. #2
    CPoly CPoly ist gerade online Mitglied Weizenbier
    tutorials.de Premium-User
    Registriert seit
    Sep 2009
    Beiträge
    2.445
    Code javascript:
    1
    2
    3
    
    synchronize(dein_objekt) {
        //Code, der sicher auf dem Objekt arbeiten kann, weil kein anderer Thread darauf zugreifen darf
    }

    Weiterführendes:
    http://docs.oracle.com/javase/tutori.../syncmeth.html

    http://en.wikipedia.org/wiki/Race_condition
    http://en.wikipedia.org/wiki/Synchro...ynchronization
    http://en.wikipedia.org/wiki/Monitor...hronization%29
    http://en.wikipedia.org/wiki/Semapho...programming%29


    Edit: Um dir die Problematik nochmal deutlich zu machen:

    Zitat Zitat von chickenwings Beitrag anzeigen
    Meine bisherige Idee wäre, dass der Thread, der sich das Objekt zum Lesen herausholt, in eine zweite Map ablegt, die nur Objekte beinhaltet, die gerade bearbeitet werden. So könnte ein anderer Thread dort nachsehen, ob es schreibbar ist oder nicht.
    Das Problem ist, dass das "Nachsehen" auch synchronisiert werden müsste! Denn ansonsten können sich zwei Threads genau beim Nachsehen in die Quere kommen und am Ende denken beide, Sie könnten auf dem Objekt arbeiten.


    A und B sind Threads
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    A prüft, ob Objekt in Liste und stellt fest, es ist nicht drin
    A wird unterbrochen
    B startet
    B prüft, ob Objekt in Liste und stellt fest, es ist nicht drin
    B fügt Objekt zu Liste hinzu
    B arbeitet auf Objekt
    B wird unterbrochen
    A startet
    A fügt Objekt zu Liste hinzu (ist jetzt doppelt drin)
    A arbeitet auf Objekt (obwohl B das auch gerade tut)
    Geändert von CPoly (31.01.12 um 11:02 Uhr)
     

  3. #3
    slowfly slowfly ist offline Mitglied Bronze
    Registriert seit
    Mar 2009
    Beiträge
    40
    Zitat Zitat von CPoly Beitrag anzeigen
    [javascript]
    Das Problem ist, dass das "Nachsehen" auch synchronisiert werden müsste! Denn ansonsten können sich zwei Threads genau beim Nachsehen in die Quere kommen und am Ende denken beide, Sie könnten auf dem Objekt arbeiten.
    Ne, das sollten sie eigentlich nicht denken, weil der sync ja auf das gleiche Objekt gemacht wird.

    Thread A -> map.get(key).
    Thread A -> lock auf obj
    Thread B -> map.get(key)
    Thread B -> wartet bis obj freigegeben ist.
    Thread A -> fertig, aus dem sync-block raus.
    Thread B -> wird angestossen und macht weiter.

    Kann man schön mit Thread.sleep und thread-dumps nachvollziehen,...

    Gruss
    slowy
     

  4. #4
    CPoly CPoly ist gerade online Mitglied Weizenbier
    tutorials.de Premium-User
    Registriert seit
    Sep 2009
    Beiträge
    2.445
    Zitat Zitat von slowfly Beitrag anzeigen
    Ne, das sollten sie eigentlich nicht denken, weil der sync ja auf das gleiche Objekt gemacht wird.

    Thread A -> map.get(key).
    Thread A -> lock auf obj
    Thread B -> map.get(key)
    Thread B -> wartet bis obj freigegeben ist.
    Thread A -> fertig, aus dem sync-block raus.
    Thread B -> wird angestossen und macht weiter.

    Kann man schön mit Thread.sleep und thread-dumps nachvollziehen,...

    Gruss
    slowy
    Aber bei seiner Idee gibt es keinen sync Block, der ist ihm ja offenbar unbekannt, sonst gäbe es diesen Thread nicht. Ich bezog mich mit der Aussage ausschließlich auf seine Idee, eine Art Semaphor selbst zu bauen, was aber ohne die passenden Mechanismen auch in die Hose geht.
     

  5. #5
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo,

    Es soll also n Threads geben, die auf eine Map zugreifen. In dieser Map sind bestimmte Objekte enthalten. Wenn nun ein Thread sich ein Objekt herausholt, um es zu bearbeiten, soll explizit dieses Objekt für den Zugriff durch andere Threads gesperrt werden.
    Was meinst du mit "soll für andere Threads gesperrt sein" genau? Sollen andere Threads überhaupt keinen Zugriff mehr auf das Objekt bekommen?

    Oder sollen die anderen Threads zwar noch Zurgiff auf das Objekt haben aber nur noch lesend auf zugreifen können? -> Mutationen wären dann exklusiv nur von dem derzeitigen "Owner" möglich...?


    Gruß Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  6. #6
    chickenwings chickenwings ist offline Mitglied Gold
    Registriert seit
    Nov 2005
    Beiträge
    213
    Hi Tom,

    der Lesezugriff muss nicht exklusiv sein, jedoch der Schreibzugriff. Während des Schreibens, darf das Objekt (logischerweise) auch von keinen anderen Thread gelesen werden. Das Objekt darf nur einen spezifischen Zustand haben, der bekannt ist.

    Grüsse,
    chickenwings
     

  7. #7
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo,

    der Lesezugriff muss nicht exklusiv sein, jedoch der Schreibzugriff. Während des Schreibens, darf das Objekt (logischerweise) auch von keinen anderen Thread gelesen werden. Das Objekt darf nur einen spezifischen Zustand haben, der bekannt ist.
    Hört sich ganz nach java.util.concurrent.locks.ReadWriteLock an...

    Gruß Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  8. #8
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo,

    suchst du vielleicht sowas in der Art?
    Der LockingWrapper dient quasi als SynchronizationProxy zum Zugriff auf das BusinessObject
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    
    package de.tutorials.training;
     
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
     
    public class MapGuardExample {
      public static void main(String[] args) {
        ConcurrentMap<Integer, LockingWrapper> map = new ConcurrentHashMap<Integer, LockingWrapper>();
        map.put(0, new LockingWrapper(new BusinessObject()));
     
        int readerCount = 5;
        int writerCount = 2;
     
        ExecutorService es = Executors.newFixedThreadPool(readerCount + writerCount);
        for (int i = 0; i < readerCount; i++) {
          es.submit(new Reader(map));
        }
     
        for (int i = 0; i < writerCount; i++) {
          es.submit(new Writer(map));
        }
      }
     
     
      static abstract class Worker implements Runnable {
        private final ConcurrentMap<Integer, LockingWrapper> map;
     
        public Worker(ConcurrentMap<Integer, LockingWrapper> map) {
          this.map = map;
        }
     
        @Override
        public void run() {
          while (true) {
            op(map.get(0));
          }
        }
     
        abstract void op(LockingWrapper lockingWrapper);
      }
     
      static class Reader extends Worker {
        public Reader(ConcurrentMap<Integer, LockingWrapper> map) {
          super(map);
        }
     
     
        @Override
        void op(LockingWrapper lockingWrapper) {
          lockingWrapper.read();
        }
      }
     
      static class Writer extends Worker {
        public Writer(ConcurrentMap<Integer, LockingWrapper> map) {
          super(map);
        }
     
     
        @Override
        void op(LockingWrapper lockingWrapper) {
          if (Math.random() < 0.1) { // 10% write probability
            lockingWrapper.write();
          }
        }
      }
     
      static class BusinessObject {
        
        private final AtomicInteger state = new AtomicInteger();
        
        public void write() {
          System.out.println(Thread.currentThread().getId() + " writes to " + this  + " " + state.incrementAndGet());
          try {
            Thread.sleep((long) (1000 * Math.random()));
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
     
     
        public void read() {
          System.out.println(Thread.currentThread().getId() + " reads from " + this + " " + state.get());
        }
        
        @Override
        public String toString() {
          return "BO@"+ System.identityHashCode(this);
        }
      }
     
      static class LockingWrapper {
        private final ReadWriteLock lock = new ReentrantReadWriteLock();
        
        private final BusinessObject bo;
     
        public LockingWrapper(BusinessObject bo) {
          this.bo = bo;
        }
     
     
        public void write() {
          lock.writeLock().lock();
          try {
            bo.write();
          } finally {
            lock.writeLock().unlock();
          }
        }
     
     
        public void read() {
          lock.readLock().lock();
          try {
            bo.read();
          } finally {
            lock.readLock().unlock();
          }
        }
      }
     
    }

    Ausgabe:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    
    13 reads from BO@753416466 0
    10 reads from BO@753416466 0
    11 reads from BO@753416466 0
    9 reads from BO@753416466 0
    12 reads from BO@753416466 0
    9 reads from BO@753416466 0
    11 reads from BO@753416466 0
    10 reads from BO@753416466 0
    13 reads from BO@753416466 0
    13 reads from BO@753416466 0
    13 reads from BO@753416466 0
    13 reads from BO@753416466 0
    10 reads from BO@753416466 0
    11 reads from BO@753416466 0
    9 reads from BO@753416466 0
    12 reads from BO@753416466 0
    9 reads from BO@753416466 0
    11 reads from BO@753416466 0
    10 reads from BO@753416466 0
    13 reads from BO@753416466 0
    11 reads from BO@753416466 0
    9 reads from BO@753416466 0
    12 reads from BO@753416466 0
    14 writes to BO@753416466 1
    14 writes to BO@753416466 2
    14 writes to BO@753416466 3
    15 writes to BO@753416466 4
    15 writes to BO@753416466 5
    15 writes to BO@753416466 6
    15 writes to BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    13 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    10 reads from BO@753416466 7
    11 reads from BO@753416466 7
    13 reads from BO@753416466 7
    11 reads from BO@753416466 7
    12 reads from BO@753416466 7
    9 reads from BO@753416466 7
    10 reads from BO@753416466 7
    11 reads from BO@753416466 7
    13 reads from BO@753416466 7
    14 writes to BO@753416466 8
    14 writes to BO@753416466 9
    14 writes to BO@753416466 10
    15 writes to BO@753416466 11
    ...

    Gruß Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  9. #9
    chickenwings chickenwings ist offline Mitglied Gold
    Registriert seit
    Nov 2005
    Beiträge
    213
    Hi Tom,

    uhi, das sieht schon mal aus, als ginge es in die richtige Richtung.
    Ich will mir mal das Beispiel zu Gemüte führen, ist doch eine schon recht ausgewachsene Implementierung.

    Vielen Dank für Deine Hinweise
    chickenwings
     

  10. #10
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo,

    Btw. ein viel einfacherer Ansatz wäre der, in der Map nur Immutable Business Objects abzulegen. Will man einen Map-Eintrag verändern, so muss man eine neues (geändertes) Business Object an der stelle in die ConcurrentMap via map.replace(key, old,new) bzw. map.replace(key,new) einfügen. Die replace Operation verläuft dabei atomar. Deshalb gibt es da auch keine Probleme wenn mehrere Threads konkurrierend auf die Elemete der Map zugreifen.
    Siehe: http://docs.oracle.com/javase/6/docs...html#replace(K, V, V)

    Gruß Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

Ähnliche Themen

  1. Antworten: 5
    Letzter Beitrag: 12.11.09, 08:56
  2. Zugriff auf Objekt
    Von liquidbeats im Forum Flash Plattform
    Antworten: 2
    Letzter Beitrag: 02.02.09, 16:51
  3. Zugriff auf ein Objekt
    Von SaschaT im Forum Flash Plattform
    Antworten: 4
    Letzter Beitrag: 13.01.08, 14:14
  4. Antworten: 3
    Letzter Beitrag: 30.03.07, 07:42
  5. Zugriff auf Objekt
    Von jenno im Forum Flash Plattform
    Antworten: 7
    Letzter Beitrag: 02.05.05, 14:24