JavaRush /Blog Jawa /Random-JV /Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - ...
Viacheslav
tingkat

Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi

Diterbitake ing grup

Pambuka

Dadi, kita ngerti manawa ana utas ing Jawa, sing bisa diwaca ing review " Sampeyan Ora Bisa Ngrusak Jawa nganggo Utas: Bagian I - Utas ". Utas dibutuhake kanggo nindakake karya bebarengan. Mulane, kemungkinan banget yen benang bakal sesambungan karo siji liyane. Ayo ngerti kepiye kedadeyan kasebut lan kontrol dhasar apa sing kita duwe. Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 1

ngasilaken

Metode Thread.yield () misterius lan arang digunakake. Ana akeh variasi saka deskripsi ing Internet. Kanggo sawetara sing nulis babagan sawetara jinis antrian benang, ing ngendi benang bakal mudhun kanthi njupuk prioritas. Ana sing nulis yen thread bakal ngganti status saka mlaku dadi runnable (sanajan ora ana divisi menyang status kasebut, lan Jawa ora mbedakake antarane). Nanging ing kasunyatan, kabeh iku luwih ora dingerteni lan, ing pangertèn, prasaja. Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 2Ing topik dokumentasi metode, yieldana bug " JDK-6416721: (spec thread) Ndandani Thread.yield() javadoc ". Yen sampeyan maca, jelas yen metode kasebut yieldmung menehi rekomendasi menyang panjadwal thread Jawa yen thread iki bisa diwenehi wektu eksekusi sing kurang. Nanging apa sing bakal kelakon, manawa panjadwal bakal ngrungokake rekomendasi lan apa sing bakal ditindakake ing umum gumantung saka implementasine JVM lan sistem operasi. Utawa mungkin saka sawetara faktor liyane. Kabeh kebingungan kasebut kemungkinan amarga mikir maneh babagan multithreading sajrone pangembangan basa Jawa. Sampeyan bisa maca liyane ing review " Brief Pambuka kanggo Java Thread.yield () ".

Turu - Mudhun asleep thread

Utas bisa uga turu sajrone eksekusi. Iki minangka jinis interaksi sing paling gampang karo benang liyane. Sistem operasi ing ngendi mesin virtual Java diinstal, ing ngendi kode Java dieksekusi, duwe jadwal thread dhewe, sing diarani Thread Scheduler. Iku kang nemtokaken thread kanggo mbukak nalika. Programmer ora bisa sesambungan karo penjadwal iki langsung saka kode Jawa, nanging bisa, liwat JVM, njaluk panjadwal kanggo ngaso thread kanggo sawetara wektu, kanggo "dilebokake kanggo turu." Sampeyan bisa maca liyane ing artikel " Thread.sleep () "Lan" Carane Multithreading dianggo ". Menapa malih, sampeyan bisa mangerteni carane Utas bisa digunakake ing Windows OS: " Internals Windows Thread ". Saiki kita bakal weruh karo mripat kita dhewe. Ayo simpen kode ing ngisor iki menyang file HelloWorldApp.java:
class HelloWorldApp {
    public static void main(String []args) {
        Runnable task = () -> {
            try {
                int secToWait = 1000 * 60;
                Thread.currentThread().sleep(secToWait);
                System.out.println("Waked up");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Thread thread = new Thread(task);
        thread.start();
    }
}
Nalika sampeyan bisa ndeleng, kita duwe tugas sing ngenteni 60 detik, sawise program rampung. Kita ngumpulake javac HelloWorldApp.javalan mbukak java HelloWorldApp. Iku luwih apik kanggo miwiti ing jendhela kapisah. Contone, ing Windows bakal kaya iki: start java HelloWorldApp. Nggunakake printah jps, kita ngerteni PID proses kasebut lan mbukak dhaptar benang kanthi nggunakake jvisualvm --openpid pidПроцесса: Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 3Kaya sing sampeyan ngerteni, benang kita wis mlebu status Turu. Nyatane, turu ing thread saiki bisa ditindakake kanthi luwih apik:
try {
	TimeUnit.SECONDS.sleep(60);
	System.out.println("Waked up");
} catch (InterruptedException e) {
	e.printStackTrace();
}
Sampeyan mbokmenawa wis ngelingi yen kita proses nang endi wae InterruptedException? Ayo padha ngerti sebabe.

Interrupting thread utawa Thread.interrupting

Masalahe yaiku nalika benang ngenteni turu, ana sing pengin ngganggu ngenteni iki. Ing kasus iki, kita nangani pangecualian kasebut. Iki ditindakake sawisé cara kasebut Thread.stopdiumumake Deprecated, i.e. outdated lan undesirable kanggo nggunakake. Alesan kanggo iki yaiku nalika metode kasebut diarani, stopbenang kasebut mung "mateni", sing ora bisa ditebak. Kita ora bisa ngerti kapan aliran bakal mandheg, kita ora bisa njamin konsistensi data. Mbayangno yen sampeyan nulis data menyang file banjur stream kasebut dirusak. Mulane, padha mutusaké sing bakal luwih logis ora kanggo mateni aliran, nanging kanggo ngandhani iku kudu diselani. Carane nanggepi iki gumantung ing aliran dhewe. Rincian liyane bisa ditemokake ing Oracle " Kenapa Thread.stop ora digunakake? " Ayo ndeleng conto:
public static void main(String []args) {
	Runnable task = () -> {
		try {
			TimeUnit.SECONDS.sleep(60);
		} catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.interrupt();
}
Ing conto iki, kita ora bakal ngenteni 60 detik, nanging bakal langsung nyithak 'Interrupted'. Iki amarga kita disebut cara thread interrupt. Cara iki nyetel "gendera internal sing diarani status interupsi". Tegese, saben thread duwe gendera internal sing ora bisa diakses langsung. Nanging kita duwe cara asli kanggo sesambungan karo gendera iki. Nanging iki ora mung cara. Utas bisa uga ana ing proses eksekusi, ora ngenteni apa-apa, nanging mung nindakake tumindak. Nanging bisa nyedhiyakake manawa dheweke pengin ngrampungake ing titik tartamtu ing karyane. Tuladhane:
public static void main(String []args) {
	Runnable task = () -> {
		while(!Thread.currentThread().isInterrupted()) {
			//Do some work
		}
		System.out.println("Finished");
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.interrupt();
}
Ing conto ing ndhuwur, sampeyan bisa ndeleng sing daur ulang whilebakal mbukak nganti thread diselani externally. Sing penting kanggo ngerti babagan gendera isInterrupted yaiku yen kita nyekel InterruptedException, bendera kasebut isInterrupteddireset, banjur isInterruptedbakal bali palsu. Ana uga cara statis ing kelas Utas sing mung ditrapake kanggo Utas saiki - Thread.interrupted () , nanging cara iki ngreset flag palsu! Sampeyan bisa maca liyane ing bab " Thread Interruption ".

Gabung - Nunggu thread liyane rampung

Jinis ngenteni sing paling gampang yaiku ngenteni thread liyane rampung.
public static void main(String []args) throws InterruptedException {
	Runnable task = () -> {
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.join();
	System.out.println("Finished");
}
Ing conto iki, thread anyar bakal turu kanggo 5 detik. Ing wektu sing padha, benang utama bakal ngenteni nganti benang turu tangi lan rampung karyane. Yen sampeyan ndeleng liwat JVisualVM, kahanan thread bakal katon kaya iki: Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 4Thanks kanggo alat ngawasi, sampeyan bisa ndeleng apa sing kedadeyan karo benang kasebut. Cara kasebut joincukup prasaja, amarga mung cara kanthi kode java sing dieksekusi waitnalika benang sing diarani urip. Sawise thread mati (ing mandap), Enteni wis mungkasi. Iku kabeh keajaiban saka metode join. Mulane, ayo pindhah menyang bagean sing paling menarik.

Monitor Konsep

Ing multithreading ana sing kaya Monitor. Umumé, tembung monitor diterjemahaké saka basa Latin minangka "pengawas" utawa "pengawas". Ing kerangka artikel iki, kita bakal nyoba ngelingi inti, lan kanggo sing pengin, aku njaluk sampeyan nyilem menyang materi saka pranala kanggo rincian. Ayo miwiti lelampahan kanthi spesifikasi basa Jawa, yaiku JLS: " 17.1. Sinkronisasi ". Iku ngandika ing ngisor iki: Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 5Pranyata metu sing kanggo tujuan sinkronisasi antarane Utas, Jawa nggunakake mekanisme tartamtu disebut "Monitor". Saben obyek duwe monitor sing ana gandhengane, lan benang bisa ngunci utawa mbukak kunci. Sabanjure, kita bakal nemokake tutorial latihan ing situs web Oracle: " Kunci lan Sinkronisasi Intrinsik ". Tutorial iki nerangake yen sinkronisasi ing Jawa dibangun ing babagan entitas internal sing dikenal minangka kunci intrinsik utawa kunci monitor. Asring kunci kuwi mung disebut "monitor". Kita uga ndeleng maneh manawa saben obyek ing Jawa duwe kunci intrinsik sing ana gandhengane. Sampeyan bisa maca " Jawa - Kunci Intrinsik lan Sinkronisasi ". Sabanjure, penting kanggo mangerteni carane obyek ing Jawa bisa digandhengake karo monitor. Saben obyek ing Jawa duwe header - jinis metadata internal sing ora kasedhiya kanggo programmer saka kode, nanging mesin virtual kudu bisa karo obyek bener. Header obyek kalebu MarkWord sing katon kaya iki: Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 6

https://edu.netbeans.org/contrib/slides/java-overview-and-java-se6.pdf

Artikel saka Habr migunani banget ing kene: " Nanging kepiye cara multithreading? Bagean I: sinkronisasi ." Kanggo artikel iki, sampeyan kudu nambah katrangan saka Ringkesan blok tugas saka bugtaker JDK: " JDK-8183909 ". Sampeyan bisa maca bab sing padha ing " JEP-8183909 ". Dadi, ing Jawa, monitor digandhengake karo obyek lan benang bisa mblokir utas iki, utawa uga ujar "entuk kunci". Conto paling prasaja:
public class HelloWorld{
    public static void main(String []args){
        Object object = new Object();
        synchronized(object) {
            System.out.println("Hello World");
        }
    }
}
Dadi, nggunakake tembung kunci, synchronizedutas saiki (ing baris kode kasebut dieksekusi) nyoba nggunakake monitor sing ana gandhengane karo obyek kasebut objectlan "njaluk kunci" utawa "nangkep monitor" (pilihan kapindho malah luwih disenengi). Yen ora ana pratelan kanggo monitor (yaiku ora ana wong liya sing pengin nyinkronake ing obyek sing padha), Jawa bisa nyoba nindakake optimasi sing diarani "pengunci bias". Judhul obyek ing Mark Word bakal ngemot tag sing cocog lan cathetan sing dipasang ing monitor. Iki nyuda overhead nalika njupuk monitor. Yen monitor wis disambungake menyang thread liyane sadurunge, banjur ngunci iki ora cukup. JVM ngalih menyang jinis ngunci sabanjuré - ngunci dhasar. Iki nggunakake operasi comparison-and-swap (CAS). Ing wektu sing padha, header ing Mark Word ora nyimpen Mark Word maneh, nanging link menyang panyimpenan + tag diganti supaya JVM ngerti yen kita nggunakake kunci dhasar. Yen ana pratelan kanggo monitor sawetara utas (siji wis dijupuk monitor, lan kaloro nunggu monitor dirilis), banjur tag ing Mark Word diganti, lan Mark Word wiwit nyimpen referensi kanggo monitor minangka obyek - sawetara entitas internal JVM. Kaya kasebut ing JEP, ing kasus iki, spasi dibutuhake ing area memori Native Heap kanggo nyimpen entitas iki. Link menyang lokasi panyimpenan entitas internal iki bakal ana ing obyek Mark Word. Mangkono, kaya sing kita deleng, monitor pancen minangka mekanisme kanggo mesthekake sinkronisasi akses pirang-pirang benang menyang sumber daya sing dienggo bareng. Ana sawetara implementasine saka mekanisme iki sing JVM ngalih antarane. Mulane, kanggo kesederhanaan, nalika ngomong babagan monitor, kita bener-bener ngomong babagan kunci. Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 7

Disinkronake lan ngenteni kanthi ngunci

Konsep monitor, kaya sing kita deleng sadurunge, ana hubungane karo konsep "pamblokiran sinkronisasi" (utawa, sing uga disebut, bagean kritis). Ayo ndeleng conto:
public static void main(String[] args) throws InterruptedException {
	Object lock = new Object();

	Runnable task = () -> {
		synchronized (lock) {
			System.out.println("thread");
		}
	};

	Thread th1 = new Thread(task);
	th1.start();
	synchronized (lock) {
		for (int i = 0; i < 8; i++) {
			Thread.currentThread().sleep(1000);
			System.out.print("  " + i);
		}
		System.out.println(" ...");
	}
}
Ing kene, utas utama ngirim tugas menyang utas anyar, banjur langsung "nangkep" kunci kasebut lan nindakake operasi sing dawa (8 detik). Kabeh wektu iki, tugas ora bisa mlebu blok kanggo eksekusi synchronized, amarga kunci wis dikuwasani. Yen benang ora bisa entuk kunci, bakal ngenteni ing monitor. Sanalika ditampa, bakal terus eksekusi. Nalika thread ninggalake monitor, iku ngeculake kunci. Ing JVisualVM bakal katon kaya iki: Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 8Nalika sampeyan bisa ndeleng, status ing JVisualVM diarani "Monitor" amarga thread diblokir lan ora bisa manggoni monitor. Sampeyan uga bisa ngerteni negara thread ing kode, nanging jeneng negara iki ora pas karo istilah JVisualVM, sanajan padha. Ing kasus iki, th1.getState()daur ulang forbakal bali BLOCKED , amarga Nalika daur ulang mlaku, monitor lockdikuwasani maindening benang, lan benang th1diblokir lan ora bisa terus digunakake nganti kunci bali. Saliyane pamblokiran sinkronisasi, kabeh cara bisa disinkronake. Contone, metode saka kelas HashTable:
public synchronized int size() {
	return count;
}
Ing siji unit wektu, cara iki bakal dileksanakake mung siji thread. Nanging kita butuh kunci, ta? Ya aku butuh. Ing kasus metode obyek, kunci bakal this. Ana diskusi menarik babagan topik iki: " Apa ana kauntungan kanggo nggunakake Metode Sinkronisasi tinimbang Blok sing Disinkronake? ". Yen cara statis, banjur kunci ora bakal this(amarga kanggo cara statis ora bisa this), nanging obyek kelas (Contone, Integer.class).

Ngenteni lan ngenteni ing monitor. Cara notifikasi lan notifyAll

Utas duwe cara ngenteni liyane, sing disambungake menyang monitor. Boten kados sleeplan join, iku ora bisa mung disebut. Lan jenenge wait. Cara kasebut dieksekusi waiting obyek ing monitor sing pengin ngenteni. Ayo ndeleng conto:
public static void main(String []args) throws InterruptedException {
	    Object lock = new Object();
	    // task будет ждать, пока его не оповестят через lock
	    Runnable task = () -> {
	        synchronized(lock) {
	            try {
	                lock.wait();
	            } catch(InterruptedException e) {
	                System.out.println("interrupted");
	            }
	        }
	        // После оповещения нас мы будем ждать, пока сможем взять лок
	        System.out.println("thread");
	    };
	    Thread taskThread = new Thread(task);
	    taskThread.start();
        // Ждём и после этого забираем себе лок, оповещаем и отдаём лок
	    Thread.currentThread().sleep(3000);
	    System.out.println("main");
	    synchronized(lock) {
	        lock.notify();
	    }
}
Ing JVisualVM bakal katon kaya iki: Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 10Kanggo ngerti cara kerjane, sampeyan kudu ngelingi yen metode waitkasebut . Iku misale jek aneh sing thread related cara ing . Nanging ing kene ana jawabane. Kaya sing kita eling, saben obyek ing Jawa nduweni header. Header ngemot macem-macem informasi layanan, kalebu informasi babagan monitor-data babagan status ngunci. Lan kita elinga, saben obyek (yaiku saben conto) duwe asosiasi karo entitas JVM internal disebut kunci intrinsik, kang uga disebut monitor. Ing conto ing ndhuwur, tugas nerangake yen kita ngetik blok sinkronisasi ing monitor sing digandhengake karo . Yen bisa entuk kunci ing monitor iki, banjur . Utas sing nindakake tugas iki bakal ngeculake monitor , nanging bakal gabung karo antrian utas sing nunggu kabar ing monitor . Antrian utas iki diarani WAIT-SET, sing luwih bener nggambarake inti. Iku luwih saka pesawat saka antrian. Utas nggawe utas anyar kanthi tugas tugas, diwiwiti lan ngenteni 3 detik. Iki ngidini, kanthi kemungkinan dhuwur, benang anyar kanggo nyekel kunci sadurunge benang lan antri ing monitor. Sawise benang kasebut mlebu blok sinkronisasi lan nindakake kabar babagan benang ing monitor. Sawise kabar dikirim, thread ngeculake monitor , lan thread anyar (sing sadurunge ngenteni) terus dieksekusi sawise ngenteni monitor dirilis. Sampeyan bisa ngirim kabar mung siji saka utas ( ) utawa kabeh utas ing antrian bebarengan ( ). Sampeyan bisa maca liyane ing " Bedane antarane notify () lan notifyAll () ing Jawa ". Wigati dimangerteni manawa pesenan kabar gumantung saka implementasi JVM. Sampeyan bisa maca liyane ing " Carane ngatasi keluwen karo notify lan notifyall? ". Sinkronisasi bisa ditindakake tanpa nemtokake obyek. Iki bisa ditindakake nalika ora bagean kode sing kapisah disinkronake, nanging kabeh cara. Contone, kanggo cara statis kunci bakal obyek kelas (dipikolehi liwat ): notifyjava.lang.ObjectObjectlockwaitlocklockmainmainmainlockmainlocklocknotifynotifyAll.class
public static synchronized void printA() {
	System.out.println("A");
}
public static void printB() {
	synchronized(HelloWorld.class) {
		System.out.println("B");
	}
}
Ing babagan nggunakake kunci, loro cara kasebut padha. Yen cara kasebut ora statis, banjur sinkronisasi bakal ditindakake miturut arus instance, yaiku, miturut this. Miturut cara, sadurunge kita ngomong yen nggunakake cara getStatesampeyan bisa njaluk status thread. Dadi ing kene ana thread sing diantrekake dening monitor, status bakal WAITING utawa TIMED_WAITING yen metode kasebut waitnemtokake watesan wektu tunggu. Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 11

Siklus urip saka thread

Kaya sing wis dingerteni, aliran kasebut ngganti statuse sajrone urip. Intine, owah-owahan kasebut minangka siklus urip benang. Nalika thread mung digawe, wis status NEW. Ing posisi iki, durung diwiwiti lan Java Thread Scheduler durung ngerti apa-apa bab thread anyar. Supaya penjadwal thread ngerti babagan thread, sampeyan kudu nelpon thread.start(). Banjur thread bakal pindhah menyang negara RUNNABLE. Ana akeh skema sing ora bener ing Internet ing ngendi negara Runnable lan Running dipisahake. Nanging iki salah, amarga ... Jawa ora mbedakake status "siap mlaku" lan "mlaku". Nalika thread urip nanging ora aktif (ora Runnable), ana ing salah siji saka rong negara:
  • BLOCKED - ngenteni entri menyang bagean sing dilindhungi, i.e. menyang synchonizedblok.
  • WAITING - ngenteni thread liyane adhedhasar kondisi. Yen kondisi kasebut bener, panjadwal thread bakal miwiti thread.
Yen thread nunggu wektu, iku ing negara TIMED_WAITING. Yen utas ora mlaku maneh (rampung kanthi sukses utawa kajaba), bakal dadi status TERMINATED. Kanggo ngerteni kahanan utas (kahanane), cara kasebut digunakake getState. Utas uga duwe cara isAlivesing ngasilake bener yen benang ora Diakhiri.

LockSupport lan parkir Utas

Wiwit Java 1.6 ana mekanisme menarik sing diarani LockSupport . Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 12Kelas iki nggandhengake "ijin" utawa ijin karo saben utas sing nggunakake. Telpon cara parkbali langsung yen ijin kasedhiya, manggoni ijin sing padha sak nelpon. Yen ora, diblokir. Nelpon cara unparknggawe ijin kasedhiya yen durung kasedhiya. Ijin mung ana 1. Ing Java API , LockSupport. SemaphoreAyo katon ing conto prasaja:
import java.util.concurrent.Semaphore;
public class HelloWorldApp{

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(0);
        try {
            semaphore.acquire();
        } catch (InterruptedException e) {
            // Просим разрешение и ждём, пока не получим его
            e.printStackTrace();
        }
        System.out.println("Hello, World!");
    }
}
Kode iki bakal ngenteni selawase amarga semaphore saiki duwe 0 ijin. Lan nalika diarani kode acquire(yaiku, njaluk ijin), benang ngenteni nganti entuk ijin. Amarga kita ngenteni, kita kudu ngolah InterruptedException. Apike, semaphore ngetrapake negara benang sing kapisah. Yen kita katon ing JVisualVM, kita bakal weruh sing negara kita ora Enteni, nanging Park. Sampeyan ora bisa ngrusak Jawa nganggo benang: Part II - sinkronisasi - 13Ayo ndeleng conto liyane:
public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            //Запаркуем текущий поток
            System.err.println("Will be Parked");
            LockSupport.park();
            // Как только нас распаркуют - начнём действовать
            System.err.println("Unparked");
        };
        Thread th = new Thread(task);
        th.start();
        Thread.currentThread().sleep(2000);
        System.err.println("Thread state: " + th.getState());

        LockSupport.unpark(th);
        Thread.currentThread().sleep(2000);
}
Status thread bakal NUNGGU, nanging JVisualVM mbedakake waitantarane saka synchronizedlan parksaka LockSupport. Kenapa iki penting banget LockSupport? Ayo bali menyang Java API lan deleng Thread State WAITING . Nalika sampeyan bisa ndeleng, mung ana telung cara kanggo njaluk menyang. 2 cara - iki waitlan join. Lan sing katelu yaiku LockSupport. Kunci ing Jawa dibangun kanthi prinsip sing padha LockSupportlan makili piranti sing luwih dhuwur. Ayo dadi nyoba kanggo nggunakake siji. Ayo katon, contone, ing ReentrantLock:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class HelloWorld{

    public static void main(String []args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        Runnable task = () -> {
            lock.lock();
            System.out.println("Thread");
            lock.unlock();
        };
        lock.lock();

        Thread th = new Thread(task);
        th.start();
        System.out.println("main");
        Thread.currentThread().sleep(2000);
        lock.unlock();
    }
}
Kaya ing conto sadurunge, kabeh prasaja ing kene. lockngenteni wong ngeculake sumber. Yen kita katon ing JVisualVM, kita bakal weruh yen thread anyar bakal diparkir nganti mainthread menehi kunci. Sampeyan bisa maca liyane babagan kunci kene: " Pemrograman multithreaded ing Jawa 8. Bagean loro. Nyelarasake akses menyang obyek sing bisa diowahi " lan " Java Lock API. Teori lan conto panggunaan ." Kanggo luwih ngerti implementasine kunci, migunani kanggo maca babagan Phazer ing ringkesan " Kelas Phaser ". Lan ngomong babagan macem-macem sinkronisasi, sampeyan kudu maca artikel ing Habré " Java.util.concurrent.* Synchronizers Reference ".

Total

Ing review iki, kita ndeleng cara utama utas sesambungan ing Jawa. Materi tambahan: #Viacheslav
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION