เพื่อนหลายคนอาจเคยได้ยินคำหลักที่ผันผวนและอาจใช้มัน ก่อนหน้า Java 5 มันเป็นคำหลักที่ขัดแย้งกันเนื่องจากการใช้ในโปรแกรมมักจะส่งผลให้ผลลัพธ์ที่ไม่คาดคิด หลังจาก Java 5 คำหลักที่ผันผวนได้กลับมามีชีวิตชีวาอีกครั้ง
ฟังก์ชั่นของคำหลักที่ผันผวนคือการทำให้เธรดทั้งหมดในการแชร์ระบบที่มองเห็นได้จากตัวแปรที่แก้ไขโดยคำหลักและสามารถห้ามมิให้หน่วยความจำการทำงานของเธรดจากตัวแปรแคชที่แก้ไขโดยความผันผวน
ระเหย 2 สถานการณ์การใช้งาน:
1. การมองเห็น: Java มีคำหลักที่ผันผวนเพื่อให้แน่ใจว่าการมองเห็น
เมื่อตัวแปรที่ใช้ร่วมกันถูกแก้ไขโดยความผันผวนจะช่วยให้มั่นใจได้ว่าค่าที่แก้ไขจะได้รับการปรับปรุงเป็นหน่วยความจำหลักทันทีและเมื่อเธรดอื่นจำเป็นต้องอ่านมันจะอ่านค่าใหม่ในหน่วยความจำ
อย่างไรก็ตามตัวแปรที่ใช้ร่วมกันทั่วไปไม่สามารถรับประกันการมองเห็นได้เนื่องจากไม่แน่นอนเมื่อตัวแปรที่ใช้ร่วมกันปกติถูกเขียนไปยังหน่วยความจำหลักหลังจากแก้ไขแล้ว เมื่อเธรดอื่นอ่านค่าเดิมอาจยังอยู่ในหน่วยความจำดังนั้นจึงไม่สามารถรับประกันการมองเห็นได้
นอกจากนี้การซิงโครไนซ์และล็อคยังสามารถตรวจสอบการมองเห็นได้ ซิงโครไนซ์และล็อคสามารถตรวจสอบให้แน่ใจว่ามีเพียงหนึ่งเธรดที่ได้รับการล็อคในเวลาเดียวกันและเรียกใช้รหัสการซิงโครไนซ์ ก่อนที่จะปล่อยล็อคการปรับเปลี่ยนของตัวแปรจะถูกรีเฟรชไปยังหน่วยความจำหลัก ดังนั้นการมองเห็นสามารถรับประกันได้
มาดูรหัสชิ้นหนึ่งก่อน หากเธรด 1 ถูกเรียกใช้ก่อนและเธรด 2 จะถูกดำเนินการในภายหลัง:
// เธรด 1boolean stop = false; ในขณะที่ (! หยุด) {dosomething ();} // เธรด 2stop = true;รหัสนี้เป็นโค้ดทั่วไปและหลายคนอาจใช้วิธีการมาร์กอัปนี้เมื่อขัดจังหวะเธรด แต่อันที่จริงแล้วรหัสนี้จะทำงานได้อย่างถูกต้องหรือไม่? เธรดจะถูกขัดจังหวะหรือไม่? ไม่จำเป็น บางทีเวลาส่วนใหญ่รหัสนี้สามารถขัดจังหวะเธรดได้ แต่อาจทำให้เธรดไม่ถูกขัดจังหวะ (แม้ว่าความเป็นไปได้นี้จะเล็กมากเมื่อสิ่งนี้เกิดขึ้นมันจะทำให้เกิดการวนซ้ำ)
มาอธิบายว่าทำไมรหัสนี้อาจทำให้เธรดไม่ขัดจังหวะ ตามที่อธิบายไว้ก่อนหน้านี้แต่ละเธรดมีหน่วยความจำการทำงานของตัวเองในระหว่างการทำงานดังนั้นเมื่อเธรด 1 ทำงานอยู่มันจะคัดลอกค่าของตัวแปรหยุดและใส่ไว้ในหน่วยความจำการทำงานของตัวเอง
จากนั้นเมื่อเธรด 2 เปลี่ยนค่าของตัวแปรหยุด แต่ไม่มีเวลาเขียนลงในหน่วยความจำหลักเธรด 2 จะทำสิ่งอื่น ๆ จากนั้นเธรด 1 ไม่ทราบเกี่ยวกับการเปลี่ยนแปลงของเธรด 2 ในตัวแปรหยุดดังนั้นมันจะยังคงวนเวียนอยู่ต่อไป
แต่หลังจากแก้ไขด้วยความผันผวนแล้วมันจะแตกต่างกัน:
ครั้งแรก: การใช้คำหลักที่ผันผวนจะบังคับให้ค่าที่แก้ไขจะถูกเขียนไปยังหน่วยความจำหลักทันที
ประการที่สอง: หากคุณใช้คำหลักที่ผันผวนเมื่อเธรด 2 ปรับเปลี่ยนบรรทัดแคชของตัวแปรแคชหยุดในหน่วยความจำการทำงานของเธรด 1 จะไม่ถูกต้อง (หากสะท้อนให้เห็นในชั้นฮาร์ดแวร์บรรทัดแคชที่สอดคล้องกันในแคช L1 หรือ L2 ของ CPU ไม่ถูกต้อง);
ประการที่สาม: เนื่องจากสายแคชของตัวแปรแคชหยุดในหน่วยความจำการทำงานของเธรด 1 ไม่ถูกต้องเธรด 1 จะอ่านในหน่วยความจำหลักเมื่ออ่านค่าของตัวแปรหยุดอีกครั้ง
จากนั้นเมื่อเธรด 2 ปรับเปลี่ยนค่าหยุด (แน่นอนมี 2 การดำเนินการที่นี่แก้ไขค่าในหน่วยความจำการทำงานของเธรด 2 จากนั้นเขียนค่าที่แก้ไขไปยังหน่วยความจำ) สายแคชของตัวแปรแคชหยุดในหน่วยความจำการทำงานของเธรด 1 จะไม่ถูกต้อง เมื่อเธรด 1 อ่านพบว่าสายแคชนั้นไม่ถูกต้อง มันจะรอให้ที่อยู่หน่วยความจำหลักที่สอดคล้องกันของสายแคชที่จะอัปเดตจากนั้นอ่านค่าล่าสุดในหน่วยความจำหลักที่เกี่ยวข้อง
จากนั้นเธรด 1 อ่านเป็นค่าที่ถูกต้องล่าสุด
2. ตรวจสอบความเป็นระเบียบเรียบร้อย
บูลีนผันแปรเริ่มต้น = false; // เธรด 1: บริบท = loadContext (); เริ่มต้น = true; // เธรด 2: ในขณะที่ (! inited) {sleep ()} dosomethingwithconfig (บริบท);ตรวจสอบให้แน่ใจว่าบริบทได้รับการเริ่มต้น
3. การตรวจสอบสองครั้ง
คลาส Singleton {อินสแตนซ์ Singleton แบบคงที่แบบคงที่ส่วนตัว = null; Private Singleton () {} public Static Singleton getInstance () {ถ้า (อินสแตนซ์ == null) {ซิงโครไนซ์ (singleton.class) {ถ้า (อินสแตนซ์ == null)ข้างต้นเป็นคำอธิบายโดยละเอียดเกี่ยวกับบทบาทและการใช้คำหลักที่ผันผวนใน Java ที่แนะนำโดยบรรณาธิการ ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!