Rumah >Java >javaTutorial >Memahami Pengoptimuman Kunci JVM
여러 동시 작업을 수행할 수 있는 강력하고 확장 가능한 애플리케이션을 개발하려면 동시성이 매우 중요합니다. 그러나 이를 위해서는 동기화 측면에서 대가를 지불해야 합니다. 잠금 획득 및 해제에 수반되는 오버헤드로 인해 성능 비용이 발생합니다. 이러한 성능 비용을 줄이기 위해 편향된 잠금, 잠금 제거, 잠금 거칠기화, 경량 및 중량 잠금 개념 등 여러 가지 최적화 기능이 JVM에 통합되었습니다.
이 기사에서는 이러한 최적화에 대해 더 자세히 살펴보고 멀티 스레드 Java 애플리케이션에서 동기화를 향상시키는 방법을 살펴봅니다.
Java 잠금 기본 사항
Java에서는 블록이나 메소드의 동기화를 통해 한 번에 하나의 스레드만 코드의 중요한 섹션을 실행할 수 있습니다. 이는 다중 스레드 환경 내에서 리소스 공유를 고려할 때 특히 중요합니다. Java는 내장 잠금을 사용하여 이를 구현합니다. 때로는 동기화된 블록을 사용하여 스레드에 대한 액세스를 관리하는 데 도움이 되는 개체 또는 클래스와 연결된 모니터라고도 합니다.
스레드 안전성을 위해서는 동기화가 필수이지만 경합이 낮거나 전혀 없을 경우 비용이 상당히 많이 들 수 있습니다. JVM 최적화가 프레임에 들어가는 곳입니다. 따라서 잠금 비용이 절감되고 전반적인 성능이 향상됩니다.
1. 편향된 잠금
편향 잠금이란 무엇인가요?
편향된 잠금은 잠금 획득 오버헤드를 줄이는 것을 목표로 하는 최적화입니다. 이는 단일 스레드에 의해 지배되거나 단일 스레드에 의해 가장 많이 액세스되는 잠금 획득 비용을 줄이기 위해 최적화되었습니다. 이러한 프로그램은 종종 다른 스레드와의 경합 없이 동일한 스레드에 의해 잠금을 획득하고 해제합니다. JVM은 이 패턴을 인식하고 해당 특정 스레드에 대한 잠금을 바이어스할 수 있습니다. 다음 잠금 획득은 거의 무료입니다.
편향 잠금은 어떻게 작동하나요?
편향 잠금이 활성화되면 스레드가 처음으로 잠금을 획득할 때 잠금이 해당 스레드 쪽으로 편향되게 됩니다. 스레드의 ID는 잠금 개체의 헤더에 기록되며 해당 스레드에 의한 후속 잠금 획득에는 동기화가 전혀 포함되지 않습니다. 잠금이 현재 스레드 쪽으로 편향되어 있는지 확인하기만 하면 됩니다. 이는 매우 빠르고 비차단 작업입니다. .
다른 스레드가 잠금을 획득하려고 하면 바이어스가 취소되고 JVM은 바이어스되지 않은 표준 잠금 메커니즘으로 돌아갑니다. 이 단계에서는 이제 표준 잠금이 되며 두 번째 스레드는 표준 잠금 프로세스를 통해 이를 획득해야 합니다.
편향 잠금의 이점
성능: 바이어스 잠금에서 동일한 스레드 획득은 거의 무료 잠금 획득입니다.
따라서 다른 스레드가 잠금 획득에 참여할 기회가 없으므로 경합 처리가 필요하지 않습니다.
낮은 오버헤드: 경합이 발생하는 경우를 제외하고는 잠금 상태를 변경하거나 동기화 관련 메타데이터를 수정할 필요가 없습니다.
편향 잠금은 언제 사용되나요?
편향된 잠금은 단일 스레드 애플리케이션이나 다중 스레딩에서 잠금 경합이 낮은 애플리케이션과 같이 주로 동일한 스레드에서 잠금에 액세스하는 애플리케이션에 유용합니다. 대부분의 JVM에서는 기본적으로 활성화되어 있습니다.
편향 잠금 비활성화 방법
편향 잠금은 기본적으로 활성화되어 있지만 아래와 같이 JVM 플래그를 사용하여 비활성화할 수도 있습니다.
-XX:-BiasedLocking 사용
2. 잠금 제거
잠금 제거란 무엇인가요?
잠금 제거는 JVM이 일부 불필요한 동기화(잠금)를 완전히 제거하는 매우 강력한 최적화입니다. JIT 컴파일 중에 코드를 검사하여 동기화가 필요하지 않음을 확인합니다. 이는 일반적으로 하나의 스레드에서만 잠금에 액세스했거나 JVM을 사용하여 동기화하는 개체가 다른 스레드 내에서 동일한 개체를 공유하지 않는 경우에 발생합니다. JVM이 더 이상 필요하지 않다고 판단하면 잠금이 제거됩니다.
잠금 제거는 어떻게 작동하나요?
JIT 컴파일의 이스케이프 분석 단계에서 JVM은 객체가 단일 스레드에 국한되어 있는지 아니면 로컬 컨텍스트에서만 사용되는지 확인합니다. 개체가 자신을 생성한 스레드의 범위를 벗어나지 않기 때문에 해당 개체에 대한 동기화를 제거할 수 있다면 그렇게 됩니다.
Sebagai contoh, jika objek dicipta dan digunakan sepenuhnya dalam kaedah (dan tidak dikongsi merentasi utas), JVM menyedari tiada utas lain yang mungkin boleh mengakses objek itu, dan oleh itu semua penyegerakan adalah berlebihan. Dalam kes sedemikian, pengkompil JIT hanya menghapuskan kunci sama sekali.
Sifar Mengunci Overhed: Menghapuskan penyegerakan yang tidak perlu juga akan menghalang JVM daripada membayar kos memperoleh dan melepaskan kunci di tempat pertama.
Keupayaan Lebih Tinggi: Segerak mati kadangkala boleh membawa kepada daya pemprosesan yang lebih tinggi bagi aplikasi, terutamanya jika kod itu mengandungi banyak blok disegerakkan.
Lihat sekeping kod ini:
public void someMethod() { StringBuilder sb = new StringBuilder(); synchronized (sb) { sb.append("Hello"); sb.append("World"); } }
Dalam kes ini, penyegerakan pada sb tidak diperlukan kerana StringBuilder hanya digunakan dalam someMethod dan tidak dikongsi antara urutan lain. Dengan melihat perkara ini, JVM boleh melakukan analisis melarikan diri untuk mengeluarkan kunci.
3. Kunci Kasar
Apakah Lock Coarsening?
Pengasar kunci ialah pengoptimuman di mana JVM mengembangkan skop kunci untuk menutup lebih banyak ketulan kod dan bukannya memperoleh dan melepaskan kunci dalam gelung atau bahagian kecil kod secara berterusan.
Kerja Mengasar Kunci
Jika JVM mendapati bahawa gelung ketat atau berbilang blok kod bersebelahan memperoleh dan melepaskan kunci terlalu kerap, ia boleh mengecilkan kunci dengan mengambil kunci di luar gelung atau merentasi beberapa blok kod. Ini menjadikan pemerolehan dan pelepasan berulang tanpa kunci mahal dan membolehkan benang memegang kunci untuk lebih banyak lelaran.
Contoh Kod: Kunci Kasar
Pertimbangkan coretan kod ini:
for (int i = 0; i < 1000; i++) { synchronized (lock) { // Do something } }
Kekasaran kunci menolak pemerolehan kunci di luar gelung, jadi benang memperoleh kunci sekali sahaja:
synchronized (lock) { for (int i = 0; i < 1000; i++) { // Do something } }
JVM boleh meningkatkan prestasi secara mendadak dengan mengelakkan lebih banyak perolehan dan pelepasan kunci.
Faedah Mengunci Kasar
Kurang Kebebasan Mengunci Overhed: Mengasar mengelakkan pemerolehan dan pelepasan kunci, terutamanya dalam kod tempat liputan, seperti gelung yang telah diulang beribu kali.
Prestasi yang Dipertingkat:
Mengunci untuk tempoh yang lebih lama meningkatkan prestasi jika dibandingkan dengan senario di mana, tanpa penguncian, kunci sedemikian akan diperoleh dan dilepaskan beberapa kali.
4. Kunci Ringan dan Berat Berat
JVM menggunakan dua teknik penguncian berbeza berdasarkan tahap perselisihan antara utas. Teknik sedemikian termasuk kunci ringan dan kunci berat.
Pengunci Ringan
Penguncian ringan berlaku tanpa ketiadaan kunci perbalahan, bermakna hanya satu utas yang cuba memperoleh kunci itu. Dalam senario sedemikian, JVM mengoptimumkan pemerolehan menggunakan operasi CAS apabila cuba memperoleh kunci, yang boleh berlaku tanpa penyegerakan kelas berat.
Kunci Heavyweight
Sekiranya beberapa utas ingin mendapatkan kunci yang sama; iaitu, terdapat pertikaian, JVM meningkatkan ini kepada penguncian kelas berat. Ini akan melibatkan menyekat benang pada peringkat OS dan mengurusnya menggunakan primitif penyegerakan peringkat OS. Kunci berat adalah lebih perlahan kerana ia sebenarnya memerlukan OS untuk melakukan penukaran konteks, serta untuk mengurus urutan.
Peningkatan Kunci
Jika pertikaian timbul pada kunci ringan, JVM mungkin meningkatkannya kepada kunci kelas berat. Peningkatan di sini bermakna beralih daripada kunci tahap pengguna yang pantas kepada kunci tahap OS yang lebih mahal yang termasuk penyekatan benang.
Faedah Kunci Ringan
Pemerolehan kunci yang pantas: Apabila tiada perbalahan, kunci ringan jauh lebih cepat daripada kunci kelas berat kerana ia mengelakkan penyegerakan peringkat OS.
Sekatan yang dikurangkan: Tanpa pertengkaran, benang tidak menyekat dan meningkat secara linear dengan kependaman yang lebih rendah.
Kelemahan Kunci Heavyweight
Overhed Prestasi: Kunci kelas berat menanggung kos penyekatan benang, penukaran konteks dan urutan bangun dengan penurunan prestasi pada rejim perbalahan yang sangat tinggi.
Semua pengoptimuman ini membantu JVM meningkatkan prestasi dalam aplikasi berbilang benang, jadi pembangun kini boleh menulis kod serentak yang selamat tanpa mengorbankan banyak dalam cara penyegerakan overhed. Memahami pengoptimuman ini boleh membantu pembangun mereka bentuk sistem yang lebih cekap, terutamanya dalam kes yang mempunyai penalti berprestasi tinggi untuk mengunci.
Atas ialah kandungan terperinci Memahami Pengoptimuman Kunci JVM. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!