# Kleines Verständnis Problem -> NIO -> Selector



## Kr0e (25. Mai 2008)

Hi, die Methode selectedKeys() von der Klasse Selector ist ja nicht Thread-Sicher. Wie könnte man diese synchronisieren um dies zu erreichen ? 

Meine Idee war folgende:


```
Iterator<SelectionKey> selectedKeys;
			        synchronized(socketSelector)
			        {
			        	selectedKeys = socketSelector.selectedKeys().iterator();
			        }
			        
			       synchronized(selectedKeys)
                               {  
			            while(selectedKeys.hasNext()) 
			           {
                                        //....
```

Ist das so ok ? Liefert selectedKeys() eine Refernz auf ein Object das intern von Selector verarbeitet wird ? Oder erstellt es ein neues Object jedes mal ? 

Ich bin noch nicht ganz mit der Speicherverwaltung von Java verrtaut,... bei C++ war das alles etwas durchschaubarer...
Achja noch eine Frage zu "synchronized" Was genau synchronisiert man da ? Die Referenz oder das Object im Speicher ?
Also ich meine zb. folgendes: Man erstellt 2 Referenzen auf einen Speicherplatz. So nun synchronisiert man eine davon und ändert iwas mit einer MEthode von dem Object. Könnte man nun in einem anderem Thread mit der 2ten Referenz ohne Problem auf das Object zugreifen ? Oder ist der Speicherplatz für weiteren Zugriff gesperrt ?

Grußß Chris


----------



## tuxedo (26. Mai 2008)

Wenn du da zwangs-synchronisierst, verbaust du dir wohlmöglich die ganze NIO performance. 

Schau mal hier in die "run()" Methode. So hab ich's gemacht.

Weitere Infos unter anderem hier: http://today.java.net/cs/user/print/a/350

- Alex


----------



## Kr0e (26. Mai 2008)

Hi, danke erstmal, aber hier synchronisierst du doch auch immer ?!


```
// Process any pending selector changes
// this means read/write interests and registrations
synchronized (this.pendingChanges) {
```

Oder meintest du das im bezug auf SocketSelector ??

Gruß Chris


----------



## tuxedo (26. Mai 2008)

Da synchronisiere ich auf "pendingChanges". D.h. wenn ich irgendwelche regOps ändern will was "schief" gehen könnte, dann mach ich das in den pendingChanges. Und das wird dann am Anfang der schleife gemacht. Das Ergebnis: Änderungen werden "gepuffert" und dann ausgeführt wenn es sicher ist.

- Alex


----------



## Kr0e (26. Mai 2008)

Jetzt im nachhinein weiß ich auf einmal garnicht mehr warum ich den SocketSelector synchronisieren wollte.
Ich glaube mich hat die Bemerkung "Is not thread-safe" gestört.  Nagut also du synchronisierst am Anfang die Liste pendingChanges, da sie nicht nur von der run Schleife verwendet wird richtig ?
Nämlich evt auch von public methoden, die in einem anderen Thread ausgefürhrt werden ... Hab ich bishierhin alles richtig verstanden ?

Gurß Chris


----------



## Kr0e (26. Mai 2008)

bzw... die private methoden, die zugriff auf den selector haben, dürfen von keiner public aufgerufen werden nicht war ?


----------



## tuxedo (27. Mai 2008)

Du solltest einen direkten Zugriff auf den Selector außerhalb der run() Methode vermeiden. 

Was willst du denn "unbedingt" mit dem Selector von außen anstellen?

- Alex


----------



## Kr0e (27. Mai 2008)

Naja die accept funktion wollte ich als extra methode verwenden, die wird natürlich private...

PS: die methode register vom socketchannel braucht ja den selector, ich werte das mal als "aufruf"


----------



## tuxedo (27. Mai 2008)

Accept und das reagieren auf read und write kannst du alles in der run-methode abhandeln, bzw. aus der run-methode heraus steuern. Und register wird, wenn im verlinkten Sourcecode schaust, auch nur in run() benutzt. 

Synchronisieren tu ich dann nur auf meinen "pendingChanges" Puffer. Das bremst zwar auch, aber da der selector häufiger verwendet wird als mein pendingChanges ist das irrelevant.

- Alex


----------



## Kr0e (27. Mai 2008)

JAja so ist das bei mir auch, read, write, accept wird aus der run heraus gestartet.. undzwar NUR aus der run...  falls jemand dann mal von meiner Klasse erbt muss er (A) aufpassen diese methoden nicht in einer public zu starten oder (B) ALLES in die run() methode zu packen, was allerdings ziemlich unleserlich wird...


----------

