Atomiset muuttujat: lukituksettomat päivitykset
Käytä AtomicInteger-, AtomicLong- ja AtomicReference-tyyppejä säieturvallisiin laskureihin ilman lukituksia.
Atomiset muuttujat: lukituksettomat päivitykset on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
Ei-atomisten operaatioiden ongelma
Yksinkertainen kasvatus count++ ei ole säieturvallinen — se koostuu kolmesta operaatiosta: lue, lisää, kirjoita. Samanaikaiset säikeet voivat limittyä näiden välillä, mikä aiheuttaa päivitysten katoamista. Atomiset muuttujat ratkaisevat tämän ilman lukkoja.
// UNSAFE:
int count = 0;
// Thread A reads count=0, Thread B reads count=0
// Both write 1 — second update lost!
count++; // NOT thread-safe
// SAFE:
import java.util.concurrent.atomic.*;
AtomicInteger atomicCount = new AtomicInteger(0);
atomicCount.incrementAndGet(); // atomic, lock-freeAtomicIntegerin perusteet
AtomicInteger tarjoaa kokonaislukujen operaatioita, jotka ovat atomisia CPU:n compare-and-swap (CAS) -käskyjen avulla — lukkoja ei tarvita.
AtomicInteger counter = new AtomicInteger(0);
counter.set(10); // set to 10
System.out.println(counter.get()); // 10
int prev = counter.getAndIncrement(); // returns 10, sets to 11
int curr = counter.incrementAndGet(); // sets to 12, returns 12
counter.addAndGet(5); // adds 5, returns 17
counter.decrementAndGet(); // subtracts 1, returns 16compareAndSet: CAS-operaatio
compareAndSet(expected, update) päivittää arvon atomisesti vain, jos nykyinen arvo on odotetun arvon suuruinen. Se palauttaa arvon true, jos päivitys onnistuu. Tämä muodostaa kaikkien lukottomien algoritmien perustan.
AtomicInteger ai = new AtomicInteger(5);
boolean updated = ai.compareAndSet(5, 10); // current==5? set to 10
System.out.println(updated); // true
System.out.println(ai.get()); // 10
boolean failed = ai.compareAndSet(5, 20); // current==10, not 5 → fails
System.out.println(failed); // false
System.out.println(ai.get()); // still 10AtomicLong laskureille
AtomicLong on 64-bittinen vastine. Sitä käytetään usein sekvenssigeneraattoreissa ja osumamäärien laskureissa:
AtomicLong seq = new AtomicLong(0);
// Thread-safe sequence generator:
long nextId() {
return seq.incrementAndGet();
}
System.out.println(nextId()); // 1
System.out.println(nextId()); // 2
System.out.println(nextId()); // 3AtomicBoolean
Säieturvallinen totuusarvolippu. Sitä käytetään usein kertaluonteiseen alustamiseen tai sammutussignaaleihin:
AtomicBoolean initialized = new AtomicBoolean(false);
void initOnce() {
// compareAndSet: only first caller succeeds
if (initialized.compareAndSet(false, true)) {
System.out.println("Initializing...");
// perform expensive init
} else {
System.out.println("Already initialized");
}
}AtomicReference
AtomicReference<V> tarjoaa atomiset päivitykset olio-viitteeseen. Sitä käytetään lukottomien tietorakenteiden toteuttamiseen:
import java.util.concurrent.atomic.*;
record Config(String host, int port) {}
AtomicReference<Config> configRef =
new AtomicReference<>(new Config("localhost", 8080));
// Hot-swap the configuration atomically:
Config oldConfig = configRef.get();
Config newConfig = new Config("prod.example.com", 443);
boolean swapped = configRef.compareAndSet(oldConfig, newConfig);
System.out.println(swapped); // true
System.out.println(configRef.get()); // Config[host=prod.example.com, port=443]updateAndGet / getAndUpdate
Käyttäkää funktiota atomisesti sisäisesti toteutetun CAS-uudelleenyrityssilmukan avulla:
AtomicInteger value = new AtomicInteger(10);
// Apply function atomically: square the value
int newVal = value.updateAndGet(x -> x * x);
System.out.println(newVal); // 100
// Get old, then apply:
int old = value.getAndUpdate(x -> x + 1);
System.out.println(old); // 100
System.out.println(value.get()); // 101accumulateAndGet
Yhdistäkää nykyinen arvo annettuun arvoon funktion avulla:
AtomicInteger max = new AtomicInteger(0);
// Keep running maximum:
max.accumulateAndGet(42, Math::max); // max(0, 42) = 42
max.accumulateAndGet(15, Math::max); // max(42, 15) = 42
max.accumulateAndGet(99, Math::max); // max(42, 99) = 99
System.out.println(max.get()); // 99LongAdder suuren kilpailun laskureille
Säikeiden välisen kilpailun ollessa suurta AtomicLongin CAS-uudelleenyritykset voivat heikentää suorituskykyä. LongAdder käyttää useita soluja kilpailun vähentämiseen:
import java.util.concurrent.atomic.*;
LongAdder adder = new LongAdder();
// Multiple threads can call add() with minimal contention:
adder.increment();
adder.add(5);
adder.increment();
System.out.println(adder.sum()); // 7
// Note: sum() is NOT atomic with add() — use only when no concurrent addsAtomiset taulukot
AtomicIntegerArray / AtomicLongArray tarjoavat atomiset operaatiot yksittäisille taulukon alkioille:
AtomicIntegerArray arr = new AtomicIntegerArray(5);
arr.set(0, 10);
arr.incrementAndGet(0);
arr.compareAndSet(2, 0, 42); // index 2: if 0, set 42
System.out.println(arr.get(0)); // 11
System.out.println(arr.get(2)); // 42Milloin atomisia muuttujia ja milloin lukkoja kannattaa käyttää
Käyttäkää atomisia muuttujia, kun:
- Päivitetään yhtä muuttujaa (laskureita, lippuja tai viitteitä)
- Kilpailua on vähän
- Lukottoman suorituskyvyn merkitys on suuri
Käyttäkää lukkoja, kun:
- Useita muuttujia on päivitettävä atomisesti
- Tarvitaan monimutkaista ehdollista logiikkaa
- Kilpailu on erittäin suurta (CAS-uudelleenyritykset heikentävät suorituskykyä)
Pikatarkistus
Mitä compareAndSet(expected, update) takaa?
Kertaus: atomiset muuttujat
Tärkeimmät opit:
- Atomiset tyypit käyttävät CPU:n CAS-käskyjä — ne ovat lukottomia ja säieturvallisia
- AtomicInteger/Long/Boolean/Reference yhden muuttujan atomisuuteen
- compareAndSet muodostaa lukottomien algoritmien perustan
- updateAndGet/accumulateAndGet funktionaalisiin päivityksiin
- LongAdder suuren kilpailun laskuritilanteisiin
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”Atomiset muuttujat: lukituksettomat päivitykset” ilmainen?
Kyllä – oppitunnin ”Atomiset muuttujat: lukituksettomat päivitykset” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Atomiset muuttujat: lukituksettomat päivitykset”?
Käytä AtomicInteger-, AtomicLong- ja AtomicReference-tyyppejä säieturvallisiin laskureihin ilman lukituksia. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”Atomiset muuttujat: lukituksettomat päivitykset”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- ReentrantLock ja synchronized
- ReadWriteLock lukija-kirjoittaja-tilanteissa
- Atomiset muuttujat: lukituksettomat päivitykset
- StampedLock ja optimistiset luvut