Multithreading i Java

Java Virtual Machine stöder parallell beräkning . Alla beräkningar kan utföras inom ramen för en eller flera trådar. Vi kan enkelt ställa in åtkomst till samma resurs eller objekt för flera trådar, samt sätta upp en tråd för att exekvera ett enda kodblock.

Alla utvecklare måste synkronisera arbetet med trådar under läs- och skrivoperationer för resurser som har flera trådar allokerade till dem.

Det är viktigt att du vid tidpunkten för åtkomst av resursen har uppdaterad data så att en annan tråd kan ändra den och du får den mest uppdaterade informationen. Även om vi tar exemplet med ett bankkonto, tills pengarna har kommit till det, kan du inte använda dem, så det är viktigt att alltid ha uppdaterad data. Java har speciella klasser för synkronisering och hantering av trådar.

Trä föremål

Det hela börjar med huvudtråden (huvudtråden), det vill säga åtminstone ditt program har redan en löpande tråd. Huvudtråden kan skapa andra trådar med Callable eller Runnable . Skapandet skiljer sig endast i returresultatet, Runnable returnerar inget resultat och kan inte kasta ett markerat undantag. Därför får du en bra möjlighet att bygga ett effektivt arbete med filer, men detta är mycket farligt och du måste vara försiktig.

Det är också möjligt att schemalägga trådexekvering på en separat CPU-kärna. Systemet kan enkelt flytta mellan trådar och exekvera en specifik tråd med rätt inställningar: det vill säga tråden som läser data exekveras först, så fort vi har data, sedan skickar vi det till tråden som ansvarar för validering, efter det skickar vi det till tråden för att köra lite affärslogik och en ny tråd skriver tillbaka dem. I en sådan situation behandlar 4 trådar data i sin tur och allt kommer att fungera snabbare än en tråd. Varje sådan ström konverteras till en inbyggd OS-ström, men hur den kommer att konverteras beror på JVM-implementeringen.

Klassen Tråd används för att skapa och arbeta med trådar. Den har standardkontrollmekanismer, såväl som abstrakta sådana, såsom klasser och samlingar från java.util.concurrent .

Trådsynkronisering i Java

Kommunikation tillhandahålls genom att dela åtkomst till objekt. Detta är väldigt effektivt, men samtidigt är det väldigt lätt att göra fel när man arbetar. Fel uppstår i två fall: trådstörningar - när en annan tråd stör din tråd, och minneskonsistensfel - minneskonsistens. För att lösa och förhindra dessa fel har vi olika synkroniseringsmetoder.

Trådsynkronisering i Java hanteras av monitorer, detta är en högnivåmekanism som tillåter endast en tråd att exekvera ett kodblock som skyddas av samma monitor åt gången. Monitorernas beteende beaktas i termer av lås; en bildskärm - ett lås.

Synkronisering har flera viktiga punkter som du måste vara uppmärksam på. Den första punkten är ömsesidig uteslutning - endast en tråd kan äga monitorn, så synkronisering på monitorn innebär att när en tråd går in i ett synkroniserat block som skyddas av monitorn, kan ingen annan tråd komma in i blocket som skyddas av monitorn. första tråden lämnar det synkroniserade blocket. Det vill säga att flera trådar inte kan komma åt samma synkroniserade block samtidigt.

Men synkronisering är inte bara ömsesidig uteslutning. Synkronisering säkerställer att data som skrivs till minnet före eller inom ett synkroniserat block blir synligt för andra trådar som är synkroniserade på samma monitor. Efter att ha lämnat blocket släpper vi monitorn och en annan tråd kan ta tag i den och börja exekvera detta kodblock.

När en ny tråd fångar monitorn får vi tillgång till och möjligheten att exekvera det kodblocket, och vid den tidpunkten kommer variablerna att laddas från huvudminnet. Sedan kan vi se alla poster som gjorts synliga av den tidigare utgåvan av monitorn.

En läs-skrivning på ett fält är en atomoperation om fältet antingen förklaras flyktigt eller skyddas av ett unikt lås som förvärvats före någon läs-skrivning. Men om du fortfarande stöter på ett fel får du ett felmeddelande om att beställa om (ändra ordning, ombeställning). Det visar sig i felaktigt synkroniserade flertrådade program, där en tråd kan observera effekterna som produceras av andra trådar.

Effekten av ömsesidig uteslutning och synkronisering av trådar, det vill säga deras korrekta funktion uppnås endast genom att ange ett synkroniserat block eller en metod som implicit förvärvar ett lås, eller genom att explicit erhålla ett lås. Vi kommer att prata om det nedan. Båda arbetssätten påverkar ditt minne och det är viktigt att inte glömma att arbeta med flyktiga variabler.

Flyktiga fält i Java

Om en variabel är markerad som volatil är den tillgänglig globalt. Detta betyder att om en tråd kommer åt en flyktig variabel kommer den att få sitt värde innan värdet används från cachen.

En skrivning fungerar som en bildskärmsversion, och en läsning fungerar som en bildskärmsfångst. Access utförs i en relation av typen "utfört tidigare". Om du räknar ut det, är allt som kommer att vara synligt för tråd A när den kommer åt en flyktig variabel variabeln för tråd B. Det vill säga, du kommer garanterat inte att förlora dina ändringar från andra trådar.

Flyktiga variabler är atomära, det vill säga när man läser en sådan variabel används samma effekt som när man erhåller ett lås - data i minnet förklaras ogiltiga eller felaktiga, och värdet på den flyktiga variabeln läses igen från minnet. Vid skrivning används effekten på minnet, liksom när ett lås släpps - ett flyktigt fält skrivs till minnet.

Java Samtidigt

Om du vill göra en supereffektiv och flertrådad applikation måste du använda klasserna från JavaConcurrent -biblioteket , som finns i paketet java.util.concurrent .

Biblioteket är mycket voluminöst och har olika funktionalitet, så låt oss ta en titt på vad som finns inuti och dela upp det i några moduler:

Java Samtidigt

Concurrent Collections är en uppsättning samlingar för att arbeta i en miljö med flera trådar. Istället för den grundläggande inpackningen Collections.synchronizedList med blockerande åtkomst till hela samlingen, används lås på datasegment eller väntefria algoritmer används för att läsa data parallellt.

Köer - icke-blockerande och blockerande köer för arbete i en flertrådig miljö. Icke-blockerande köer fokuserar på hastighet och drift utan att blockera trådar. Blockeringsköer är lämpliga för arbete när du behöver "bromsa" producent- eller konsumenttrådarna . Till exempel, i en situation där vissa av villkoren inte är uppfyllda, är kön tom eller full, eller det finns ingen ledig Konsument 'a.

Synkroniserare är verktyg för att synkronisera trådar. De är ett kraftfullt vapen i "parallell" datoranvändning.

Executors är ett ramverk för mer bekvämt och enkelt skapande av trådpooler, det är lätt att ställa in schemaläggning av asynkrona uppgifter för att få resultat.

Lås är många flexibla trådsynkroniseringsmekanismer jämfört med de grundläggande synkroniserade , vänta , meddela , meddela alla .

Atomer är klasser som kan stödja atomära operationer på primitiver och referenser.