ใน Java มีสองวิธีหลักในการขอล็อก (lock) ทรัพยากรร่วมกันจากหลายเธรด ได้แก่ การใช้ ReentrantLock (หรือ ReadWriteLock) และการใช้คีย์เวิร์ด synchronized
คลาส ReentrantLock ถูกเพิ่มเข้ามาในแพ็กเกจ java.util.concurrent ตั้งแต่ Java 5 เป็นการนำอินเทอร์เฟซ Lock มาใช้งานจริง ตามเอกสารของ Java การนำ Lock interface ไปใช้งานให้การดำเนินการที่ครอบคลุมมากกว่าการใช้ synchronized method
ตารางเปรียบเทียบรายละเอียด
| ลำดับ | หัวข้อ | ReentrantLock | Synchronized |
|---|---|---|---|
| 1 | การขอล็อก (Acquire Lock) | คลาส ReentrantLock มีเมธอด lock() สำหรับขอล็อกทรัพยากรร่วมกันโดยเธรด |
เพียงเขียนคีย์เวิร์ด synchronized เพื่อขอล็อก |
| 2 | การปล่อยล็อก (Release Lock) | โปรแกรมเมอร์ต้องเรียกเมธอด unlock() เอง |
ปล่อยล็อกโดยอัตโนมัติ (implicitly) |
| 3 | ความสามารถในการหยุดชั่วคราว (Interruptibility) | ใช้เมธอด lockInterruptibly() เพื่อหยุดชั่วคราวเธรดได้ |
ไม่มีวิธีหยุดชั่วคราวเธรด |
| 4 | ความเป็นธรรม (Fairness) | คอนสตรักเตอร์มีพารามิเตอร์ fairness หากตั้งค่า true ล็อกจะให้สิทธิ์เข้าถึงเธรดที่รอ lâuที่สุดก่อน | ล็อกไม่รับประกันลำดับการเข้าถึงใดๆ |
| 5 | ลำดับการปล่อยล็อก | สามารถปล่อยล็อกในลำดับใดก็ได้ | ต้องปล่อยล็อกในลำดับเดียวกับที่ขอล็อก (same order) |
ตัวอย่างโค้ด ReentrantLock
public class ReentrantLockExample implements Runnable {
private Lock lock = new ReentrantLock();
@Override
public void run() {
try {
lock.lock();
// ล็อกทรัพยากรบางอย่าง
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
ตัวอย่างโค้ด Synchronized
public class SynchronizedLockExample implements Runnable {
@Override
public void run() {
synchronized (resource) {
// ล็อกทรัพยากรบางอย่าง
}
}
}
สรุป
ReentrantLock ให้ความยืดหยุ่นและควบคุมได้มากกว่า synchronized เช่น การหยุดชั่วคราวเธรด ความเป็นธรรม และการปล่อยล็อกในลำดับที่ต้องการ แต่ synchronized สะดวกกว่าเพราะจัดการล็อกอัตโนมัติ เลือกใช้ตามความต้องการของแอปพลิเคชัน