ล็อคตรวจสอบอีกครั้ง โดยและขนาดใหญ่
กระบวนทัศน์ที่ฉันเริ่มเรียนรู้ปัญหาเมื่อฉันทำงานที่ BEA คือผู้คนจะตรวจสอบซิงเกิลในวิธีต่อไปนี้:
public Class MySingleton {
private static MySingleton s_instance;
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) { s_instance = new MySingleton(); }
}
return s_instance;
}
}
สิ่งนี้ไม่ได้ผลเนื่องจากเธรดอื่นอาจเข้าสู่บล็อกที่ซิงโครไนซ์และ s_instance จะไม่เป็นโมฆะอีกต่อไป ดังนั้นการเปลี่ยนแปลงตามธรรมชาติคือการทำให้:
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) {
if(s_instance == null) s_instance = new MySingleton();
}
}
return s_instance;
}
ไม่สามารถใช้งานได้เนื่องจาก Java Memory Model ไม่รองรับ คุณต้องประกาศ s_instance ว่ามีความผันผวนเพื่อให้มันทำงานได้และแม้กระทั่งมันจะทำงานบน Java 5 เท่านั้น
คนที่ไม่คุ้นเคยกับความซับซ้อนของ Java หน่วยความจำรุ่นระเบียบนี้ขึ้นตลอดเวลา