Judulnya adalah sebagai berikut:
testsync2 kelas publik mengimplementasikan runnable {int b = 100; Sinkronisasi void m1 () melempar interruptedException {b = 1000; Thread.sleep (500); // 6 System.out.println ("b =" + b); } Sinkronisasi void m2 () melempar InterruptedException {thread.sleep (250); // 5 b = 2000; } public static void main (string [] args) melempar interruptedException {testsync2 tt = testsync2 baru (); Thread t = utas baru (TT); // 1 t.start (); // 2 tt.m2 (); // 3 System.out.println ("Thread Utama B =" + Tt.B); // 4} @Override public void run () {coba {m1 (); } catch (InterruptedException e) {E.PrintStackTrace (); }}}Hasil output dari program ini?
Hasil output program
Utas utama B = 2000b = 1000
atau
Utas utama B = 1000B = 1000
Periksa poin pengetahuan
Di Java, program multi-threaded adalah yang paling sulit untuk dipahami dan debug. Sering kali hasil eksekusi tidak dieksekusi seperti yang kami bayangkan. Oleh karena itu, sangat sulit untuk multi-thread di Java. Saya samar -samar ingat ketika saya mengambil level bahasa C 2 di perguruan tinggi, apa pertanyaan di ++ dan banyak tingkat prioritas lainnya cocok dengan hasil output akhir. Saya ingin mengambil beberapa prioritas pelari dan pertanyaan kombinasi untuk jenis pertanyaan ini. Bacalah saja dengan mendukungnya, tetapi java multi-threading masih perlu dipahami dengan baik, sandaran tidak dapat dilakukan.
Mari kita mulai analisis singkat:
Pertanyaan ini melibatkan 2 utas (utas utama, utas anak), dan kata kunci melibatkan sinkronisasi dan utas.
Kata kunci yang disinkronkan masih cukup rumit (kadang -kadang saya tidak memahaminya dengan baik, jadi pertanyaan di atas memiliki beberapa kesalahpahaman). Fungsinya adalah untuk mewujudkan sinkronisasi utas (ada banyak metode untuk mengimplementasikan sinkronisasi utas, itu hanya semacam hal lain yang akan dibicarakan oleh artikel tindak lanjut. Beberapa implementasi dari Master Doug Lea perlu dipelajari dengan cermat). Tugasnya adalah mengunci kode yang membutuhkan sinkronisasi, sehingga hanya satu utas yang dapat memasukkan blok sinkronisasi sekaligus (pada kenyataannya, itu adalah strategi pesimistis) untuk memastikan bahwa utas hanya mengingat keamanan.
Penggunaan kata kunci umum disinkronkan
Dalam kode di atas, penggunaan yang disinkronkan sebenarnya milik kasus kedua. Langsung bertindak pada metode instan: setara dengan mengunci instance saat ini. Sebelum memasukkan kode sinkronisasi, Anda harus mendapatkan kunci instance saat ini.
Kemungkinan kesalahpahaman
1. Karena kami tidak memahami disinkronkan, berkali-kali, kami mengoperasikan metode yang disinkronkan dengan multi-threading. Ketika dua utas memanggil 2 metode sinkronisasi yang berbeda, diperkirakan tidak relevan. Gagasan ini salah paham. Langsung bertindak pada metode instan: setara dengan mengunci instance saat ini. Sebelum memasukkan kode sinkronisasi, Anda harus mendapatkan kunci instance saat ini.
2. Jika metode yang disinkronkan dipanggil. Panggilan lain ke metode normal tidak ada hubungannya, dan keduanya tidak memiliki hubungan menunggu.
Ini sangat berguna untuk analisis selanjutnya.
Thread.sleep
Safess Thread saat ini (mis. Utas yang memanggil metode ini) untuk jangka waktu tertentu, memberikan utas lain kesempatan untuk melanjutkan eksekusi, tetapi tidak melepaskan kunci objek. Dengan kata lain, jika sinkronisasi yang disinkronkan cepat, utas lain masih tidak dapat mengakses data bersama. Perhatikan bahwa metode ini perlu menangkap pengecualian, yang sangat berguna untuk analisis selanjutnya.
Proses analisis
Java dieksekusi dari metode utama. Dikatakan bahwa ada 2 utas, tetapi bahkan jika Anda memodifikasi prioritas utas di sini, itu tidak berguna. Prioritasnya hanya ketika kedua program belum dieksekusi. Sekarang, setelah kode ini dieksekusi, utas utama telah dieksekusi. Untuk variabel atribut int B = 100, tidak akan ada masalah visibilitas karena disinkronkan digunakan (dan tidak perlu mengatakan bahwa deklarasi yang mudah menguap digunakan), ketika melakukan langkah 1 (utas t = utas baru (TT); // 1) utas dalam keadaan baru dan belum mulai berfungsi. Ketika 2 langkah dijalankan (t.start (); // 2) ketika metode start dipanggil, utas sebenarnya dimulai dan memasuki keadaan yang dapat dijalankan. Negara yang dapat dilalui berarti dapat dieksekusi dan semuanya siap, tetapi itu tidak berarti bahwa itu harus dieksekusi pada CPU. Apakah ada eksekusi nyata tergantung pada penjadwalan CPU layanan. Di sini, ketika melakukan 3 langkah, Anda harus terlebih dahulu mendapatkan kunci (karena Start perlu memanggil metode asli, dan semuanya siap setelah penggunaan selesai, tetapi itu tidak berarti bahwa itu harus dieksekusi pada CPU. Apakah ada eksekusi nyata tergantung pada penjadwalan CPU layanan, dan kemudian metode run akan dipanggil dan metode M1 akan dijalankan). Faktanya, tidak masalah apakah utas. Sheep dalam dua metode yang disinkronkan, mungkin menambah kesulitan untuk kebingungan. Ketika 3 langkah dieksekusi, utas anak sebenarnya siap segera, tetapi karena disinkronkan ada dan bertindak sebagai objek yang sama, utas anak harus menunggu. Karena urutan eksekusi dalam metode utama dieksekusi secara berurutan, itu harus diselesaikan setelah langkah 3 dieksekusi sebelum langkah ke -4 dapat dicapai. Karena pelaksanaan Langkah 3 selesai, utas anak dapat mengeksekusi M1. Ada masalah di sini yang mendapatkan multi-thread terlebih dahulu. Jika 4 langkah diperoleh terlebih dahulu, maka utas utama B = 2000. Jika utas anak M1 diperoleh, B mungkin telah ditugaskan ke 1000 atau sebelum 4 langkah ditetapkan, hasil yang mungkin adalah utas utama B = 1000 atau utas utama B = 2000. Jika 6 langkah dihapus di sini, maka B = Jalankan sebelum dan utas utama B = sebelumnya tidak pasti. Namun, karena ada 6 langkah, apa pun yang terjadi, utas utama B = ada di depan, sehingga tergantung pada situasi jika sama dengan 1000 atau 2000. Setelah itu, B = 1000 pasti diperbaiki.
Beberapa saran untuk multi-threading
Ada juga beberapa tips untuk dibagikan dalam artikel berikutnya. Multi-threading sangat penting dan sulit. Saya berharap semua orang akan menghabiskan lebih banyak waktu untuk itu.
Beberapa teknik debugging untuk multithreading
Karena breakpoint, semua utas harus berhenti ketika melewati breakpoint, yang menyebabkan titik ini terputus terus -menerus, yang sangat tidak nyaman. Ada breakpoint bersyarat di Eclispe, dan Anda dapat berhenti ketika kondisinya terpenuhi, jadi ini nyaman.
Meringkaskan
Di atas adalah pertanyaan wawancara Java yang paling sulit dalam sejarah yang diperkenalkan oleh editor kepada Anda. Saya harap ini akan membantu Anda. Jika Anda memiliki pertanyaan, silakan tinggalkan saya pesan dan editor akan membalas Anda tepat waktu. Terima kasih banyak atas dukungan Anda ke situs web Wulin.com!