Bagaimana mesin maya Java melakukan penyegerakan utas

Semua program Java disusun ke dalam file kelas, yang mengandungi bytecodes, bahasa mesin mesin virtual Java. Artikel ini melihat bagaimana penyegerakan utas ditangani oleh mesin maya Java, termasuk kod bytek yang berkaitan. (1,750 patah perkataan)

Under The Hood bulan ini melihat penyegerakan utas dalam bahasa Java dan mesin maya Java (JVM). Artikel ini adalah yang terakhir dalam siri artikel bytecode panjang yang saya mulakan pada musim panas lalu. Ini menerangkan satu-satunya dua opkod yang berkaitan secara langsung dengan penyegerakan utas, opkod yang digunakan untuk memasuki dan keluar monitor.

Benang dan data yang dikongsi

Salah satu kekuatan bahasa pengaturcaraan Java adalah sokongannya untuk multithreading di peringkat bahasa. Sebilangan besar sokongan ini berpusat pada penyelarasan akses ke data yang dikongsi di antara pelbagai utas.

JVM mengatur data aplikasi Java yang berjalan ke dalam beberapa area data runtime: satu atau lebih tumpukan Java, timbunan, dan area metode. Untuk latar belakang kawasan memori ini, lihat artikel Under the Hood yang pertama : "Mesin maya yang ramping dan bermakna."

Di dalam mesin maya Java, setiap utas diberikan tumpukan Java , yang berisi data yang tidak dapat diakses oleh benang lain, termasuk pemboleh ubah lokal, parameter, dan nilai pengembalian setiap metode yang diminta oleh utas. Data pada timbunan terhad kepada jenis primitif dan rujukan objek. Di JVM, tidak mungkin meletakkan gambar objek sebenar di timbunan. Semua objek berada di timbunan.

Hanya ada satu timbunan di dalam JVM, dan semua utas membagikannya. Tumpukan itu tidak mengandungi apa-apa selain objek. Tidak ada cara untuk meletakkan jenis primitif tunggal atau rujukan objek di timbunan - perkara-perkara ini mesti menjadi sebahagian daripada objek. Susunan berada di timbunan, termasuk susunan jenis primitif, tetapi di Jawa, susunan juga objek.

Selain tumpukan Java dan timbunan, data tempat lain yang mungkin berada di JVM adalah area metode , yang berisi semua variabel kelas (atau statis) yang digunakan oleh program. Kawasan kaedah serupa dengan timbunan kerana hanya mengandungi jenis primitif dan rujukan objek. Tidak seperti timbunan, bagaimanapun, pemboleh ubah kelas di kawasan kaedah dikongsi oleh semua utas.

Objek dan kunci kelas

Seperti yang dijelaskan di atas, dua kawasan memori di mesin maya Java mengandungi data yang dikongsi oleh semua utas. Ini adalah:

  • Tumpukan, yang mengandungi semua objek
  • Kawasan kaedah, yang mengandungi semua pemboleh ubah kelas

Sekiranya beberapa utas perlu menggunakan objek yang sama atau pemboleh ubah kelas secara serentak, aksesnya ke data mesti diuruskan dengan betul. Jika tidak, program ini akan mempunyai tingkah laku yang tidak dapat diramalkan.

Untuk menyelaraskan akses data bersama di antara banyak utas, mesin maya Java mengaitkan kunci dengan setiap objek dan kelas. Kunci adalah seperti hak istimewa yang hanya dapat dimiliki oleh satu utas dalam satu masa. Sekiranya utas ingin mengunci objek atau kelas tertentu, ia meminta JVM. Pada suatu ketika selepas utas meminta JVM untuk kunci - mungkin tidak lama lagi, mungkin kemudian, mungkin tidak pernah - JVM memberikan kunci ke utas. Apabila utas tidak lagi memerlukan kunci, ia mengembalikannya ke JVM. Sekiranya utas lain meminta kunci yang sama, JVM menyerahkan kunci ke utas itu.

Kunci kelas sebenarnya dilaksanakan sebagai kunci objek. Apabila JVM memuat fail kelas, ia akan membuat contoh kelas java.lang.Class. Apabila anda mengunci kelas, anda sebenarnya mengunci Classobjek kelas itu .

Thread tidak perlu mendapatkan kunci untuk mengakses pemboleh ubah instance atau kelas. Jika utas memperoleh kunci, bagaimanapun, tidak ada utas lain yang dapat mengakses data terkunci sehingga utas yang memiliki kunci melepaskannya.

Monitor

JVM menggunakan kunci bersama dengan monitor . Monitor pada dasarnya adalah penjaga kerana mengawasi urutan kod, memastikan hanya satu utas pada satu masa yang melaksanakan kod tersebut.

Setiap monitor dikaitkan dengan rujukan objek. Apabila utas tiba pada arahan pertama dalam sekumpulan kod yang berada di bawah pengawasan monitor, utas mesti memperoleh kunci pada objek yang dirujuk. Benang tidak dibenarkan menjalankan kod sehingga ia mendapat kunci. Setelah memperoleh kunci, utas memasuki blok kod terlindung.

Apabila benang meninggalkan blok, tidak kira bagaimana ia meninggalkan blok, ia melepaskan kunci pada objek yang berkaitan.

Pelbagai kunci

Satu utas dibenarkan mengunci objek yang sama berkali-kali. Untuk setiap objek, JVM mengekalkan jumlah frekuensi objek dikunci. Objek yang tidak dikunci mempunyai bilangan sifar. Apabila utas memperoleh kunci untuk pertama kalinya, jumlahnya bertambah menjadi satu. Setiap kali utas memperoleh kunci pada objek yang sama, jumlahnya bertambah. Setiap kali utas melepaskan kunci, kiraannya akan dikurangkan. Apabila kiraan mencapai sifar, kunci dilepaskan dan disediakan untuk benang lain.

Blok yang disegerakkan

Dalam terminologi bahasa Java, koordinasi beberapa utas yang harus mengakses data bersama disebut penyegerakan . Bahasa ini menyediakan dua cara terbina dalam untuk menyegerakkan akses ke data: dengan penyataan yang diselaraskan atau kaedah yang diselaraskan.

Penyataan yang disegerakkan

Untuk membuat pernyataan yang disegerakkan, anda menggunakan synchronizedkata kunci dengan ungkapan yang menilai rujukan objek, seperti dalam reverseOrder()kaedah di bawah:

class KitchenSync { private int[] intArray = new int[10]; void reverseOrder() { synchronized (this) { int halfWay = intArray.length / 2; for (int i = 0; i < halfWay; ++i) { int upperIndex = intArray.length - 1 - i; int save = intArray[upperIndex]; intArray[upperIndex] = intArray[i]; intArray[i] = save; } } } }

Dalam kes di atas, pernyataan yang terdapat di dalam blok yang disegerakkan tidak akan dilaksanakan sehingga kunci diperoleh pada objek semasa ( this). Sekiranya bukannya thisrujukan, ekspresi menghasilkan rujukan ke objek lain, kunci yang berkaitan dengan objek itu akan diperoleh sebelum utas diteruskan.

Dua opkod, monitorenterdan monitorexit, digunakan untuk blok penyegerakan dalam kaedah, seperti yang ditunjukkan dalam jadual di bawah.

Jadual 1. Monitor

Kod Op Operan Penerangan
monitorenter tiada pop objekref, dapatkan kunci yang berkaitan dengan objekref
monitorexit tiada pop objekref, lepaskan kunci yang berkaitan dengan objekref

Ketika monitorenterditemui oleh mesin maya Java, ia memperoleh kunci untuk objek yang disebut oleh objekref pada tumpukan. Sekiranya benang sudah memiliki kunci untuk objek itu, jumlahnya akan bertambah. Setiap kali monitorexitdijalankan untuk utas pada objek, kiraannya akan dikurangkan. Apabila kiraan mencapai sifar, monitor dilepaskan.

Lihat urutan bytecode yang dihasilkan oleh reverseOrder()kaedah KitchenSynckelas.

Note that a catch clause ensures the locked object will be unlocked even if an exception is thrown from within the synchronized block. No matter how the synchronized block is exited, the object lock acquired when the thread entered the block definitely will be released.

Synchronized methods

To synchronize an entire method, you just include the synchronized keyword as one of the method qualifiers, as in:

class HeatSync { private int[] intArray = new int[10]; synchronized void reverseOrder() { int halfWay = intArray.length / 2; for (int i = 0; i < halfWay; ++i) { int upperIndex = intArray.length - 1 - i; int save = intArray[upperIndex]; intArray[upperIndex] = intArray[i]; intArray[i] = save; } } }

The JVM does not use any special opcodes to invoke or return from synchronized methods. When the JVM resolves the symbolic reference to a method, it determines whether the method is synchronized. If it is, the JVM acquires a lock before invoking the method. For an instance method, the JVM acquires the lock associated with the object upon which the method is being invoked. For a class method, it acquires the lock associated with the class to which the method belongs. After a synchronized method completes, whether it completes by returning or by throwing an exception, the lock is released.

Coming next month

Now that I have gone through the entire bytecode instruction set, I will be broadening the scope of this column to include various aspects or applications of Java technology, not just the Java virtual machine. Next month, I'll begin a multi-part series that gives an in-depth overview of Java's security model.

Bill Venners telah menulis perisian secara profesional selama 12 tahun. Berpusat di Silicon Valley, dia menyediakan perkhidmatan perundingan dan latihan perisian dengan nama Artima Software Company. Selama bertahun-tahun ia telah mengembangkan perisian untuk industri elektronik, pendidikan, semikonduktor, dan insurans jiwa pengguna. Dia telah memprogram dalam banyak bahasa di banyak platform: bahasa pemasangan di berbagai mikropemproses, C di Unix, C ++ di Windows, Java di Web. Dia adalah pengarang buku: Inside the Java Virtual Machine, yang diterbitkan oleh McGraw-Hill.

Ketahui lebih lanjut mengenai topik ini

  • The book The Java virtual machine Specification (//www.aw.com/cp/lindholm-yellin.html), by Tim Lindholm and Frank Yellin (ISBN 0-201-63452-X), part of The Java Series (//www.aw.com/cp/javaseries.html), from Addison-Wesley, is the definitive Java virtual machine reference.
  • Previous "Under The Hood" articles:
  • "The Lean, Mean Virtual Machine" Gives an introduction to the Java virtual machine.
  • "The Java Class File Lifestyle" Gives an overview to the Java class file, the file format into which all Java programs are compiled.
  • "Java's Garbage-Collected Heap" Gives an overview of garbage collection in general and the garbage-collected heap of the Java virtual machine in particular.
  • "Bytecode Basics" Introduces the bytecodes of the Java virtual machine, and discusses primitive types, conversion operations, and stack operations in particular.
  • "Floating Point Arithmetic" Describes the Java virtual machine's floating-point support and the bytecodes that perform floating point operations.
  • "Logic and Arithmetic" Describes the Java virtual machine's support for logical and integer arithmetic, and the related bytecodes.
  • "Objects and Arrays" Describes how the Java virtual machine deals with objects and arrays, and discusses the relevant bytecodes.
  • "Exceptions" Describes how the Java virtual machine deals with exceptions, and discusses the relevant bytecodes.
  • "Cuba-Akhirnya" Menjelaskan bagaimana mesin maya Java menerapkan klausa ujung-ujungnya, dan membincangkan kod bytek yang berkaitan.
  • "Control Flow" Menjelaskan bagaimana mesin maya Java melaksanakan aliran kawalan dan membincangkan kod bytek yang berkaitan.
  • "The Architecture of Aglets" Menjelaskan cara kerja dalaman Aglets, teknologi ejen perisian berasaskan Java yang autonomi IBM.
  • "The Point of Aglets" Menganalisis utiliti ejen mudah alih dunia nyata seperti Aglets, teknologi ejen perisian autonomi berasaskan IBM.
  • "Kaedah Pemanggilan dan Pengembalian" Menjelaskan bagaimana mesin maya Java memanggil dan kembali dari kaedah, termasuk kod bytek yang berkaitan.

Kisah ini, "Bagaimana mesin maya Java melakukan penyegerakan utas" pada asalnya diterbitkan oleh JavaWorld.