13. september 2006 - 11:51Der er
25 kommentarer og 1 løsning
Problemer med Synchronized
Jeg har en ArrayList som jeg kan tilføje og hente(opdatere) elementer fra.
Da min applikation er multitrådet ønsker jeg ikke at kun én tråd kan arbejde på listen af gangen.
Fx kunne det være smart hvis alle tråde kan tilføje til listen samtidige, medmindre fx tråd 1 er ved at læse et element som tråd 2 forsøger at opdatere.
Men uanset hvad kan jeg ikke se hvordan man kan løse dette problem uden at synkronisere begge metoder. Og dette medfører netop at kun én tråd kan arbejde på liste.
har du hørt om semifore? Temmeligt grundliggende at vide når man arbejder med multithreadede applicationer... Der er helt sikkert også et bestemt design pattern der løser problmet (ved dog ikke lige hvilket).
men burder det ikke kunne løses ved at anvende det indbygget "synchronized" i java. En semafor er vel bare et tal som man tjekker før man eksekvere en blok kode, jeg er ude efter en noget mere konkret håndsrækning.
Jeg er ikke verdens mester til det her thread stas, men lavede noget ligende engang. Der var ArrayListen statisk(derved class variable) og kunne derfor tilgås fra alle threads.
Hvis ikke den er statisk burge du kunne sende dit ArrayList objekt med som parameter når du opretter en ny thread.
Ja det er noget af det jeg er ude efter. Ved godt det ikke er 100% nødvendigt, men jeg vil gerne lære hvordan man gør det så det fungere optimalt. Hvor finder man en beskrivelse af 1 write many read lock...google gav ikke nogle særligt relevante hits
Jeg var mere på udkig efter en henvisning (eller overordnet pseudokode) til noget teori omkring løsningen på dette problem end en færdig løsning. Nu har jeg fx læst i:
at man også kan lave et objekt som man dernæst kan synkronisere på hvilket giver en mulighed for at opdatere et felt men en anden tråd læser et andet felt. På denne måde undgår man unødvendig blokering som netop er det jeg er på udkig efter.
selvfølgelig kan du synkronisere på forskellige ting, men den eneste grund til de objekter i eksemplet er at man ikke kan synkronisere på long fordi de ikke er et objekt
Ved godt at ArrayList ikke er synkroniseret. Men jeg har lavet en klasse som arver fra ArrayList og de metoder som jeg bruger skriver jeg selv og synkronisere manuelt.
For at løse mit oprindelige problem overvejer jeg at at fjerne synkronized fra mine metoder og istedet oprette en tråd som undersøger om indkomne tråde må arbejde på listen. Den giver altså tilladelses til at tråde som ikke overlapper hinanden kan arbejde på listen, de tråde som overlapper bliver sat til at vente i en kø. På denne måde skulle det gerne være muligt at flere tråde kan arbejde samtidig i listen.
Det er ikke så meget det som er pointen. Ideen er at jeg vil undgå at der kun er én tråd som kan arbejde på listen af gangen.
Jeg har nu løst dette ved at lave 2 synkroniserede metoder "lock" og "unlock". En tråd som vil arbejde på listen kalder altid først "lock", som undersøger om der allerede er en anden tråd der arbejder på netop det samme element i listen (en oversigt over dette opbevares i et array som kun tilgås fra "lock" og "unlock").
Er det ikke nogen konflikt kalder tråden dernæst den aktuelle metode (add, get, delete).
Disse metoder er IKKE synkroniseret men indeholder kun et atomisk kald: list.add(Object), list.get(int), list.remove(object) så der skulle ikke kunne opstå nogen overskrivninger.
På denne måde kan jeg nu fx have en tråd som læser element 40 mens en anden tråd læser element 55 mens en 3. tråd undersøger om den må skrive til fx element 66.
hvis du kun vil understøtte READ og UPDATE, så behøver du ikke locke på ArrayList'en men kan nøjes med at locke på de enkelte elementer d.v.s. at Java synchronized kan out of the box tillade mere end en tråd at arbejde
hvis du også vil understøtte INSERT og DELETE så er dit locking schema ikke safe og du er nødt til at locke hele ArrayList'en
Hvad mener du med at java sync. out of the box kan tillade mere end en tråd at arbejde?
Hvis jeg har en synchroniseret add metode så er det kun én tråd der kan bruge denne af gangen.
Andre tråde kan selvfølgelig godt arbejde på ikke synkroniseret metoder.
Antag at man har 10 tråde der gerne vil indsætte i et HashMap. De har hver en unik nøgle. Synkronisere man put metoden så kan kun en tråd arbjede på HashMappet af gangen.
Alternativt kunne man vel oprette et separat objekt Q der i konstruktøren tager HashMappet som argument og den nøgle og værdi der skal indsættes.
Trådene opretter nu først Q og kalder dernæst put indefra objektet. På denne måde har hver tråd deres egen put metode og alle tråde kan indsætte på samme tid.
..hmm den sidste ide var ret uholdbar da man ikke kan forudsige hvor trådene befinder sig i deres tilsvarende objekter, ligeså vel som man ikke kan forudsige hvor de befinder sig i en enkelt metode.
hvis du kun læser eller opdaterer elementer kan du vel bruge normal synchronized ikke på ArrayList'en men på elementerne
en add metode antyder at du indsætter nye elementer og så er dit eget locking schema jo ikke godt nok og du er nød til at synkronisere adgang til ArrayList
hvis alle synkroniserer på elementet, så er det thread safe og flere tråde kan arbejde på arraylisten og det er langt hurtigere end et custom locking scheme
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.