Java - Reentrant Monitor

Hai there, para para Java yang akan datang! Hari ini, kita akan memulakan perjalanan yang menarik ke dunia Reentrant Monitors dalam Java. Jangan bimbang jika anda baru dalam programming - saya akan menjadi pandu yang ramah, dan kita akanambil langkah demi langkah. Jadi, pegang keyboard anda (tongkat sihir), dan mari kita masuk!

Java - Reentrant Monitor

Apa Itu Reentrant Monitor?

Sebelum kita masuk ke dalam hal yang rinci, mari kita faham apa itu Reentrant Monitor. Bayangkan anda berada di perpustakaan ajaib di mana hanya satu orang boleh memasuki section tertentu pada satu masa. Sekiranya anda sudah berada di section itu dan perlu masuk ke subsection yang lebih dalam? Reentrant Monitor adalah seperti pass ajaib yang membolehkan andabuat itu - masuk ke section yang anda sudah berada!

Dalam istilah Java, Reentrant Monitor membolehkan thread yang sudah memegang kunci untuk mendapatkannya lagi tanpa menyekat. Itu seperti memberikan diri anda kebenaran untuk memasuki bilik yang anda sudah berada. Menarik, kan?

Mengapa Kita Perlukan Reentrant Monitors?

Anda mungkin bertanya, "Mengapa kita perlukan pass ajaib ini?" Well, dalam dunia multithreading (di mana beberapa bahagian program dijalankan secara bersamaan), kita sering perlu melindungi sumber bersama. Reentrant Monitors membantu kita melakukan ini lebih efektif, terutama apabila kita ada method yang memanggil method lain yang juga perlu kunci yang sama.

Mengenalkan ReentrantLock

Java menyediakan kelas yang dipanggil ReentrantLock untuk implementasi Reentrant Monitors. Itu seperti pass perpustakaan ajaib kita, tetapi dalam bentuk kod!

Sintaks

Berikut cara kita mencipta dan menggunakan ReentrantLock:

import java.util.concurrent.locks.ReentrantLock;

ReentrantLock lock = new ReentrantLock();

// Untuk mengunci
lock.lock();
try {
// Kod terlindung anda disini
} finally {
// Untuk membuka kunci
lock.unlock();
}

Jangan bimbang jika ini kelihatan sedikit menakutkan. Kita akan hancurkan ini dengan beberapa contoh!

Multithreading Tanpa Reentrant Lock

Mari kita mulakan dengan contoh simple tanpa menggunakan ReentrantLock. Bayangkan kita ada counter ajaib yang beberapa ahli sihir (thread) cuba untuk meningkatkan:

public class MagicalCounter {
private int count = 0;

public void increment() {
count++;
}

public int getCount() {
return count;
}
}

Sekarang, mari kita buat beberapa thread sihir untuk meningkatkan counter ini:

public class WizardThread extends Thread {
private MagicalCounter counter;

public WizardThread(MagicalCounter counter) {
this.counter = counter;
}

public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
}

public class MagicalCounterTest {
public static void main(String[] args) throws InterruptedException {
MagicalCounter counter = new MagicalCounter();
WizardThread wizard1 = new WizardThread(counter);
WizardThread wizard2 = new WizardThread(counter);

wizard1.start();
wizard2.start();

wizard1.join();
wizard2.join();

System.out.println("Jumlah akhir: " + counter.getCount());
}
}

Jika anda jalankan ini, anda mungkin menjangkakan jumlah akhir adalah 2000 (1000 peningkatan daripada setiap sihir). Tetapi, kesedihan! Hasilnya sering kurang daripada 2000. Ini kerana sihir我们的巫师们正在踩彼此的脚——他们试图同时增加计数器,导致丢失增量。

Multithreading Dengan Reentrant Lock

Sekarang, mari kita menabur sedikit魔法 ReentrantLock pada counter kita:

import java.util.concurrent.locks.ReentrantLock;

public class MagicalCounterWithLock {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();

public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}

public int getCount() {
return count;
}
}

Mari kita hancurkan ini:

  1. Kita buat objek ReentrantLock dipanggil lock.
  2. Dalam method increment, kita panggil lock.lock() sebelum meningkatkan counter.
  3. Kita gunakan blok try-finally untuk memastikan kita selalu membuka kunci, walaupun jika ada pengecualian.
  4. Setelah meningkatkan, kita panggil lock.unlock() di blok finally.

Sekarang, jika kita menjalankan ujian WizardThread dengan MagicalCounterWithLock ini, kita akan selalu mendapat 2000 sebagai jumlah akhir. Sihir我们的巫师们现在正体面地轮流!

Multithreading Dengan Reentrant Lock Sebagai True

ReentrantLock juga ada trik lain. Kita boleh menciptanya dengan parameter keadilan:

ReentrantLock fairLock = new ReentrantLock(true);

Ketika kita mengatur keadilan ke true, kunci mengutamakan memberikan akses ke thread yang menunggu paling lama. Itu seperti membentuk barisan yang betul bagi sihir我们的巫师们!

Berikut cara kita mungkin menggunakannya:

public class FairMagicalCounter {
private int count = 0;
private ReentrantLock fairLock = new ReentrantLock(true);

public void increment() {
fairLock.lock();
try {
count++;
} finally {
fairLock.unlock();
}
}

public int getCount() {
return count;
}
}

Ini memastikan bahwa jika beberapa sihir我们的巫师们在等待增加计数器, yang menunggu paling lama akan mendapat giliran berikutnya.

Kesimpulan

Dan begitu, para sihir muda! Kita telah menjalani perjalanan melalui dunia ajaib Reentrant Monitors dalam Java. Kita telah melihat bagaimana mereka membantu kita mengelola akses bersama ke sumber dalam lingkungan multithreading, memastikan counter ajaib kita (dan objek bersama lainnya) dinaikkan dengan benar.

Ingat, seperti mana sihir yang kuat, Reentrant Monitors seharusnya digunakan bijak. Mereka sangat baik untuk mengelola akses bersama ke sumber, tetapi penggunaan yang berlebihan dapat menyebabkan penurunan performa atau bahkan deadlock (situasi di mana sihir我们的巫师们在永远等待 kunci satu sama lainnya).

Praktik spells... err, contoh kode ini, dan segera anda akan mencast sihir multithreading seperti seorang pro! Selamat berkoding, dan may your threads always be in harmony!

Credits: Image by storyset