JavaRush /Java Blog /Random-TK /Java-ny sapak bilen zaýalap bilmersiňiz: III bölüm - Özar...
Viacheslav
Dereje

Java-ny sapak bilen zaýalap bilmersiňiz: III bölüm - Özara täsir

Toparda çap edildi
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. Java-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 1

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: Java-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 2JVisualVM-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 &lt33a78231> (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-1başga birine usuly ýerine ýetirmek isleýär Friendwe ş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-1garaşýar Thread-0we 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ýasyJava-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 3 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: Java-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 4

https://www.logicbig.com/

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. Java-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 5

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 newValuebir zat ýalňyşdy we newValuebaşga-da köp zat bardy. Racearyş ýagdaýyndaky käbir sapaklar valuebu 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 bellemelidiris volatile. 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 flagaç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 volatileJVM-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 .volatileJava-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 6

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 üçin longwe 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 Integerbize hemişe 30000 görkezer, ýöne valuewagtal-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 . Java-ny sapak bilen bozup bilmersiňiz: III bölüm - özara täsir - 8

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:
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 .

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: # Wiaçeslaw
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION