Avatar billede kernelx Juniormester
17. januar 2008 - 14:17 Der er 15 kommentarer og
1 løsning

brug af synchronized

Hi,

public ArrayList<TestClass> testClasses = new ArrayList();

så har jeg en methode, som fjerner values ud af denne ArrayList
public removeElems() {
  synchronized( this.testClasses ) {
    // fjern elementer
  }
}

Jeg har givet en extern Thread mulighed for at få fat i data fra testClasses.
Denne externe methode skal gå igennem alle elementer og finde alle  elementer som opfylder bestemte ting.
/* i en anden Thread */
public findElems() {
  for ( int i=0; i<this.sourceObj.testClasses.size(); i++ ) {
    if (...) {
      ...
    }
  }
  return ...
}

denne methode er ikke fyldt med synchronized.
der er mange Threads som vil kalde denne methode. og hvis der hver gang skal blockeres hele ArrayListen, tager det lang tid for at få fat i data'erne.

Mit spørgsmål er:
Hvis methoden removeElems() bliver udført. Blockerer den så også de externe methoder som ikke arbejder med synchronized?


med venlig hilsen
KernelX
Avatar billede arne_v Ekspert
17. januar 2008 - 15:01 #1
Nej.

Synchronized er rent coorperativt - det virker kun paa andre der bruger
synchronized - det forhindrer ikke nogen adgang.
Avatar billede erikjacobsen Ekspert
17. januar 2008 - 15:57 #2
Og det derfor man kun skal bruge get- og set-metoder, og ikke referere elementer direkte.

Hvis du synes det går for langsomt, så tænk på de fejl der en gang imellem vil opstå, hvis du ikke drysser en passende mængde synchronized ud over det hele. Så vil jeg hellere at det virker, og er langsomt, end at det næsten virker, men er hurtigt ;)

Tænk også en tand længere:

  i = obj.findpos(....);
  // en anden tråd ændrer obj
  obj.erstat(i,...);
Avatar billede soerenlyn Nybegynder
17. januar 2008 - 19:19 #3
Derudover skal du aldrig have et metode-kald som "parametre" til din forløkke:

for ( int i=0; i<this.sourceObj.testClasses.size(); i++ ) {
    if (...) {
      ...
    }
}

Her vil this.sourceObj.testClasses.size() blive udført hver eneste gang du løber igennem løkken.. Du så sku' lige sætte den udenfor:

int end = this.sourceObj.testClasses.size();
for ( int i=0; i<end; i++ ) {
    if (...) {
      ...
    }
}
Avatar billede kernelx Juniormester
17. januar 2008 - 21:16 #4
husk at skrive svar
Avatar billede kernelx Juniormester
17. januar 2008 - 21:39 #5
er det OK at bruge "return" indenfor synchronized?

...
synchronized( obj ) {
  ...
  return xyz;
  ...
}
return null;
...
Avatar billede kernelx Juniormester
17. januar 2008 - 21:53 #6
er det OK at bruge en get'er i synchronized?

syncronized( this.getArrayList() ) { ... }
Avatar billede arne_v Ekspert
17. januar 2008 - 22:06 #7
Ja. Du kan godt bruge return inde i synchronized. Jeg vil dog ikke kalde det god kode stil.
Avatar billede arne_v Ekspert
17. januar 2008 - 22:07 #8
Du kan godt bruge en get i Synchronized, men jeg vil heller ikke kalde det god stil.
Avatar billede arne_v Ekspert
17. januar 2008 - 22:11 #9
Problemet med return inde i synchronized er det er et uklart program flow.

Problemet med synchronized paa return varedi af metode er at funktionaliteten
aendrer sig hvis den metode aendrer sig.

Overvej 3 forskellige getArrayList implementationer:
- en som returnerer en instans variabel
- en som returnerer en clone af en instans variabel
- en som returnerer en class variabel
Avatar billede erikjacobsen Ekspert
17. januar 2008 - 22:16 #10
Du kan jo overveje om den simple løsning er et godt startpunkt:

1) Alt i klassen er i privat, bortset fra:
2) Alle public metoder er synchronized, herunder get- og set.
3) Beregninger der ikke tåler afbrydelser ligger også i public metoder i klassen.

Det garanterer ikke at alt er uden problemer, men det er lige at gå til.
Avatar billede erikjacobsen Ekspert
17. januar 2008 - 22:18 #11
Og helt generelt vil jeg anbefale at du skjuler for dem, der kigger på din klasse udefra, at du bruger en ArrayList. Din klasse skal have sin egen funktionalitet, uanset hvilken måde du vælger at implementere den på.
Avatar billede kernelx Juniormester
18. januar 2008 - 08:36 #12
mange tak for alle tips!
husk at skrive et eller andet som svar.
Avatar billede erikjacobsen Ekspert
18. januar 2008 - 08:52 #13
Ingen point til mig, tak.
Avatar billede kernelx Juniormester
18. januar 2008 - 09:00 #14
er det klogt at bruge synchronized på en String?
Strings er jo immutable.

public void getABC() { return this.abcString; }
  eller
public void getABC() {
  String abcString = null;
  synchronized( this ) {
    abcString = this.abcString;
  }
  return abcString;
}
  eller
public void getABC() {
  String abcString = null;
  synchronized( this ) {
    abcString = new String( this.abcString );
  }
  return abcString;
}

hvilken methode er hos String den bedste - og vilken er generelt hos objekter (som ikke er immutable) den bedste?
Eller er der en bedre løsning end en af de tre?
Avatar billede arne_v Ekspert
18. januar 2008 - 15:03 #15
Der er ikke noget problem i at synche paa en String. Ethvert objekt kan bruges og man
aendrer ikke paa objektet.

To noter:

* Det goer nogen gange koden mere laeselig hvis man syncher paa det man faktisk
  skal synkronisere adgangen til

* jeg tror ikke at du kan synche paa null
Avatar billede arne_v Ekspert
18. januar 2008 - 15:03 #16
Og et svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester