/ Synchronizácia Java v singulárnom vzore - java, synchronizácia, singleton

Java synchronizovať v singulárnom vzore - java, synchronizácia, singleton

Musí sa synchronizované kľúčové slovo aplikovať na každú metódu triedy, ktorá implementuje vzor ako jeden?

public class Singleton {

private Singleton(){}

public synchronized static Singleton getInstance()
{
if(instance == null)
instance = new Singleton ();

return instance;
}

public void DoA(){
}
}

Keďže Singletons nevystavujú verejnosťkonštruktér a metóda getInstance () je synchronizovaná, nie je potrebné synchronizovať metódu DoA a akékoľvek iné verejné metódy vystavené triedou Singleton.

Je toto odôvodnenie správne?

odpovede:

17 pre odpoveď č. 1

Je to rovnako ako každá iná trieda, môže alebo nemusí byť potrebná ďalšia synchronizácia.

Zoberme si nasledujúci príklad:

public class Singleton {

private Singleton() {}

public synchronized static Singleton getInstance() { ... }

private int counter = 0;

public void addToCounter(int val) {
counter += val;
}
}

Ak má byť trieda použitá z viacerých vlákien, addToCounter() má závodný stav. Jeden spôsob, ako to opraviť je tým, že addToCounter() synchronizované:

  public synchronized void addToCounter(int val) {
count += val;
}

Existujú aj iné spôsoby, ako opraviť stav pretekov, napríklad použitím AtomicInteger:

  private final AtomicInteger counter = new AtomicInteger(0);

public void addToCounter(int val) {
counter.addAndGet(val);
}

Tu sme podmienku preteku fixovali bez použitia synchronized.


9 pre odpoveď č. 2

Účelom triedy Singleton je, že je najviac jedna inštancia a že všetky vlákna majú prístup k rovnakému objektu.

Ak by ste synchronizáciu nekombinovali getInstance môže dôjsť k nasledovnému postupu

Závit1 vstupuje getInstance()

Závit2 vstupuje getInstance()

Thread1 vyhodnocuje instance == null na true

Thread2 vyhodnocuje instance == null na true

Thread1 priradí instance a vráti sa

Thread2 reprideľuje instance = new Singleton() a vráti sa.

Teraz majú vlákna rozdielnu inštanciu triedy Singleton, čo by sa tomuto vzoru malo zabrániť.

Synchronizácia zabraňuje tomu, aby obe vlákna mohli pristupovať k rovnakému bloku kódu súčasne. Takže synchronizácia je potrebná v prostredí s viacerými vláknami pri inštancii tried singleton.

Teraz predpokladáme, že sa pokúsi viacero vlákienprístup k metódam Singletons súčasne synchronizácia môže byť potrebné aj pri týchto metódach. Najmä ak menia dáta namiesto toho, aby len čítali, je to pravda.


1 pre odpoveď č. 3

Správny (najlepší skutočný) spôsob, ako používať Singleton

private static singleton getInstance() {
if (minstance == null) {
synchronized (singleton.class) {
if (minstance == null) {
minstance = new singleton();
}
}
}
return minstance;
}

1 pre odpoveď č. 4

lenivé inicializácie a bezpečné riešenie závitov:

public class Singleton {

public static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}