Sapagyň özara täsiriniň aýratynlyklaryna gysgaça syn. Öň sapaklaryň biri-biri bilen sinhronlaşýandygyna seredýärdik. Bu gezek sapaklar biri-biri bilen täsirleşip, olaryň öňüni alyp boljakdygy barada gürleşende ýüze çykyp biljek meselelere çümeris. Çuňňur öwrenmek üçin käbir peýdaly baglanyşyklary hem hödürläris.
Bu ýerde ajaýyp mysal tapyp bilersiňiz: " Java - mowzuk açlygy we adalatlylyk ". Bu mysal, “Açlyk” -da sapaklaryň nähili işleýändigini we “Thread.sleep” -dan “Thread.wait” -e çenli kiçijik üýtgeşmäniň ýüküň deň paýlanmagyny görkezýär.
Bu wideonyň bu hakda hiç zat aýtmazlygy has gowudyr. Şonuň üçin diňe wideo baglanyşyk goýaryn. " Java - bolup geçýän zatlara düşünmek" gatnaşyklaryny okap bilersiňiz .
Giriş
Şeýlelik bilen, Java-da sapaklaryň bardygyny bilýäris, " Sapak Java-ny zaýalap bilmeýär: I bölüm - sapaklar " synynda okap bilersiňiz we synlaryň üstünde işlän sapaklarymyz biri-biri bilen sinhronlaşdyrylyp bilner ". Sapak Java-ny zaýalap bilmeýär "Talaňçylyk: II bölüm - Sinhronizasiýa ." Saplaryň biri-biri bilen nähili gatnaşygy barada gürleşmegiň wagty geldi. Umumy çeşmeleri nädip paýlaşýarlar? Munuň bilen nähili problemalar bolup biler?Öçürmek
Iň erbet mesele Deadlock. Iki ýa-da has köp sapak biri-birine hemişelik garaşsa, oňa “Deadlock” diýilýär. Oracle web sahypasyndan " Öçürmek " düşünjesiniň beýanyndan mysal alalyň :public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s has bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s has bowed back to me!%n",
this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();
}
}
Bu ýerdäki petik ilkinji gezek peýda bolup bilmez, emma programmaňyzyň ýerine ýetirilişi ýapyk bolsa, işlemegiň wagty geldi jvisualvm
: JVisualVM-de bir plugin gurnalan bolsa (Gurallar -> Pluginler arkaly), gulpuň nirede bolandygyny görüp bileris:
"Thread-1" - Thread t@12
java.lang.Thread.State: BLOCKED
at Deadlock$Friend.bowBack(Deadlock.java:16)
- waiting to lock <33a78231> (a Deadlock$Friend) owned by "Thread-0" t@11
1-nji sapak 0-njy sapakdan gulp garaşýar. Näme üçin beýle bolýar? Thread-1
ýerine ýetirip başlaýar we usuly ýerine ýetirýär Friend#bow
. Açar söz bilen bellendi synchronized
, ýagny monitory alýarys this
. Usulyň girelgesinde başga birine baglanyşyk aldyk Friend
. Indi, sapak Thread-1
başga birine usuly ýerine ýetirmek isleýär Friend
we şeýlelik bilen ondan gulp alýar. Anotheröne başga bir sapak (bu ýagdaýda Thread-0
) usuly girizmegi başaran bolsa bow
, gulp eýýäm meşgul we Thread-1
garaşýar Thread-0
we tersine. Blokirlemek çözülip bilinmeýär, şonuň üçin öldi, ýagny öldi. Ikisem ölüm gysgysy (goýberip bolmaýar) we gaçyp bolmaýan öli blok. Gulplama mowzugynda wideony görüp bilersiňiz: " Öçürmek - 1-nji ylalaşyk - Ösen Java ".
Livelock
Eger petik bar bolsa, onda Livelock barmy? Hawa, bar) Livelock, sapaklaryň daşyndan diri ýaly bolup görünýär, ýöne şol bir wagtyň özünde hiç zat edip bilmeýär, sebäbi ... işini dowam etdirmäge synanyşýan şerti ýerine ýetirilip bilinmez. Aslynda, “Livelock” petige meňzeýär, ýöne sapaklar monitora garaşýan ulgamda “asylmaýar”, ýöne hemişe bir zatlar edýär. Mysal üçin:import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class App {
public static final String ANSI_BLUE = "\u001B[34m";
public static final String ANSI_PURPLE = "\u001B[35m";
public static void log(String text) {
String name = Thread.currentThread().getName(); //like Thread-1 or Thread-0
String color = ANSI_BLUE;
int val = Integer.valueOf(name.substring(name.lastIndexOf("-") + 1)) + 1;
if (val != 0) {
color = ANSI_PURPLE;
}
System.out.println(color + name + ": " + text + color);
try {
System.out.println(color + name + ": wait for " + val + " sec" + color);
Thread.currentThread().sleep(val * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Lock first = new ReentrantLock();
Lock second = new ReentrantLock();
Runnable locker = () -> {
boolean firstLocked = false;
boolean secondLocked = false;
try {
while (!firstLocked || !secondLocked) {
firstLocked = first.tryLock(100, TimeUnit.MILLISECONDS);
log("First Locked: " + firstLocked);
secondLocked = second.tryLock(100, TimeUnit.MILLISECONDS);
log("Second Locked: " + secondLocked);
}
first.unlock();
second.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(locker).start();
new Thread(locker).start();
}
}
Bu koduň üstünligi, Java sapak meýilnamasynyň sapaklary başlamagynyň tertibine baglydyr. Ilki başlasa Thead-1
, Livelock alarys:
Thread-1: First Locked: true
Thread-1: wait for 2 sec
Thread-0: First Locked: false
Thread-0: wait for 1 sec
Thread-0: Second Locked: true
Thread-0: wait for 1 sec
Thread-1: Second Locked: false
Thread-1: wait for 2 sec
Thread-0: First Locked: false
Thread-0: wait for 1 sec
...
Mysaldan görnüşi ýaly, iki sapak hem iki gulpy tutmaga çalyşýar, ýöne şowsuz. Mundan başga-da, olar petikli däl, ýagny wizual taýdan hemme zat gowy we olar öz işini edýärler. JVisualVM-e görä, uky döwürlerini we seýilgäh döwrüni görýäris (bu sapak bir gulpy eýelemäge synanyşanda, sapaklaryň sinhronizasiýasy barada aýdanymyzda öňem aýdyp geçişimiz ýaly seýilgäh ýagdaýyna girýär ). “Livelock” mowzugynda bir mysal görüp bilersiňiz: “ Java - Thread Livelock ”.
Açlyk
Blokirlemekden başga-da, köp okamak bilen işleýän wagtyňyz başga bir mesele bar - Açlyk ýa-da “açlyk”. Bu hadysa, sapaklaryň petiklenmezligi bilen tapawutlanýar, ýöne olaryň hemmeler üçin ýeterlik serişdesi ýok. Şonuň üçin käbir sapaklar ýerine ýetiriş wagtynyň hemmesini alsa-da, beýlekiler ýerine ýetirilip bilinmez:https://www.logicbig.com/
Acearyş ýagdaýy
Köp okamak bilen işleýän wagtyňyzda "ýaryş ýagdaýy" ýaly bir zat bar. Bu hadysa, sapaklaryň öz aralarynda belli bir çeşmäni paýlaşýandygyna we koduň bu ýagdaýda dogry işlemegini üpjün etmeýän görnüşde ýazylmagyna esaslanýar. Bir mysala seredeliň:public class App {
public static int value = 0;
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
int oldValue = value;
int newValue = ++value;
if (oldValue + 1 != newValue) {
throw new IllegalStateException(oldValue + " + 1 = " + newValue);
}
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
Bu kod ilkinji gezek ýalňyşlyk döredip bilmez. Munuň ýaly bolup biler:
Exception in thread "Thread-1" java.lang.IllegalStateException: 7899 + 1 = 7901
at App.lambda$main$0(App.java:13)
at java.lang.Thread.run(Thread.java:745)
Görşüňiz ýaly, berlen wagty newValue
bir zat ýalňyşdy we newValue
başga-da köp zat bardy. Racearyş ýagdaýyndaky käbir sapaklar value
bu iki toparyň arasynda üýtgemegi başardy. Görşümiz ýaly, sapaklaryň arasynda ýaryş peýda boldy. Indi pul amallary bilen şuňa meňzeş ýalňyşlyklar goýbermegiň nähili möhümdigini göz öňüne getiriň ... Mysallary we diagrammalary şu ýerden tapyp bilersiňiz: “ Java sapakdaky ýaryş ýagdaýyny simulirlemek üçin kod ”.
Üýtgäp dur
Saplaryň özara täsiri barada aýdanymyzda, esasanam açar sözi bellemelidirisvolatile
. Simpleönekeý bir meselä seredeliň:
public class App {
public static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Runnable whileFlagFalse = () -> {
while(!flag) {
}
System.out.println("Flag is now TRUE");
};
new Thread(whileFlagFalse).start();
Thread.sleep(1000);
flag = true;
}
}
Iň gyzykly zat, ýokary ähtimallyk bilen işlemez. Täze sapak üýtgemäni görmez flag
. Muny düzetmek üçin meýdan üçin flag
açar söz görkezmeli volatile
. Nädip we näme üçin? Actionshli amallar prosessor tarapyndan ýerine ýetirilýär. Emma hasaplamanyň netijeleri bir ýerde saklanmalydyr. Bu maksat bilen prosessorda esasy ýat we apparat keşi bar. Bu prosessor keşleri, esasy ýada girmekden has çalt maglumat almak üçin kiçijik bir ýat bölegi ýalydyr. Everythingöne hemme zadyň bir erbet tarapy hem bar: keşdäki maglumatlar häzirki bolup bilmez (ýokardaky mysaldaky ýaly, baýdak gymmaty täzelenmedik wagty). Şeýlelik bilen, açar söz volatile
JVM-e üýtgeýjimizi keş etmek islemeýändigimizi aýdýar. Bu, ähli sapaklarda hakyky netijäni görmäge mümkinçilik berýär. Bu gaty ýönekeýleşdirilen formula. Bu mowzukda " JSR 133 (Java Memory Model) FAQvolatile
" -iň terjimesini okamak maslahat berilýär . Şeýle hem, “ Java Memory Model ” we “ Java Volatile Keyword ” materiallary barada has köp okamagyňyzy maslahat berýärin . Mundan başga-da, üýtgeşmeleriň atomlygy hakda däl-de, görnüklilik bilen baglanyşyklydygyny ýatdan çykarmaly däldiris . Kody "acearyş ýagdaýy" -dan alsak, "IntelliJ Idea" -da bir yşarat göreris: Bu gözleg (Gözleg) IntelliJ Idea-a 2010-njy ýylda goýberiş belliklerinde görkezilen IDEA-61117 sanynyň bir bölegi hökmünde goşuldy .volatile
Atomlyk
Atom amallary, bölüp bolmaýan amallardyr. Mysal üçin, üýtgeýjä baha bellemegiň işi atomdyr. Gynansagam, artdyrmak atom operasiýasy däl, sebäbi artdyrmak üç amal talap edýär: köne bahany alyň, oňa goşuň we bahany tygşytlaň. Atom näme üçin möhüm? Ösüş mysalynda, ýaryş ýagdaýy ýüze çyksa, islendik wagt umumy çeşme (ýagny umumy baha) birden üýtgäp biler. Mundan başga-da, 64 bitli gurluşlaryň hem atom däldigi möhümdir, mysal üçinlong
we double
. Bu ýerde has köp okap bilersiňiz: " 64 bitli bahalary okanyňyzda we ýazanyňyzda atomlygy üpjün ediň ". Atom bilen baglanyşykly meseleleriň mysalyny aşakdaky mysalda görmek bolýar:
public class App {
public static int value = 0;
public static AtomicInteger atomic = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
value++;
atomic.incrementAndGet();
}
};
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
Thread.sleep(300);
System.out.println(value);
System.out.println(atomic.get());
}
}
Atom bilen işlemek üçin ýörite synp Integer
bize hemişe 30000 görkezer, ýöne value
wagtal-wagtal üýtgär. Bu mowzukda " Java-da atom üýtgeýjilerine giriş " barada gysgaça syn bar . Atom deňeşdirmek we çalyşmak algoritmine esaslanýar. Bu hakda Habré " JDK 7 we 8-iň mysalyny ulanyp CAS we FAA-ny deňeşdirmek " atly makalada ýa-da Wikipediýada " Bir exchangea bilen deňeşdirme " atly makalada okap bilersiňiz .
http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
Öň bolup geçýär
Gyzykly we syrly bir zat bar - Öň bolýar. Akymlar barada aýdanymyzda, bu hakda okamaga-da mynasyp. Öň bolup geçýän gatnaşyklar sapaklaryň arasyndaky hereketleriň görkeziliş tertibini görkezýär. Köp düşündirişler we düşündirişler bar. Bu mowzuk boýunça iň soňky hasabatlaryň biri şu hasabat:Netijeler
Bu gözden geçirilişde, sapaklaryň özara täsiriniň aýratynlyklaryna göz aýladyk. Iseüze çykyp biljek meseleler we olary ýüze çykarmagyň we ýok etmegiň ýollaryny ara alyp maslahatlaşdyk. Mowzukdaky goşmaça materiallaryň sanawy:- Iki gezek barlanan gulplama hakda
- JSR 133 (Java ýat modeli) Soraglar (terjime)
- Ösen Java - ylalaşyk (uriuri Tkaç)
- Duglas Hawkins (Java) tarapyndan Java-da ylalaşyk düşünjeleri
GO TO FULL VERSION