ในการเขียนโปรแกรมหลายเธรดชวามักพบความผันผวน บางครั้งคำหลักนี้มักจะสับสนกับการซิงโครไนซ์หรือล็อค การวิเคราะห์เฉพาะ มีดังนี้:
ในสภาพแวดล้อมแบบมัลติเธรดจะมีปัญหาในการมองเห็นตัวแปรสมาชิก: แต่ละเธรดใน Java มีพื้นที่หน่วยความจำของสแต็กเธรดซึ่งบันทึกข้อมูลตัวแปรของเธรดเมื่อมันทำงาน เมื่อเธรดเข้าถึงค่าตัวแปรที่แน่นอนจะพบหน่วยความจำฮีปของวัตถุหรือเนื้อหาเฉพาะของสแต็ก (ประเภทข้อมูลดั้งเดิม) ตามที่อยู่ของตัวแปรจากนั้นบันทึกการคัดลอกค่าเดียวกันในสแต็กเธรดของเธรดนี้ จากนั้นการดำเนินการทั้งหมดในตัวแปรนี้ไม่มีส่วนเกี่ยวข้องกับเนื้อหาตัวแปรในสแต็กก่อนที่เธรดจะออก มันทำงานในสำเนาในสแต็กเธรด หลังจากการดำเนินการเสร็จสมบูรณ์ผลลัพธ์ของการดำเนินการจะถูกเขียนกลับไปยังหน่วยความจำหลัก หากมีสองเธรด A และ B และเพื่อนร่วมงานจะใช้ตัวแปร X; A เพิ่ม 1 ถึง X จากนั้นสำเนาที่ได้รับโดย B อาจเป็นผลมาจาก X Plus 1 หรือ X; เพื่อให้แน่ใจว่าจำเป็นต้องมีตัวแปรข้อมูลล่าสุดในหน่วยความจำเพื่อเพิ่มคำหลักที่ผันผวนดังนั้นทุกครั้งที่คุณทำงานบน X คุณจะตรวจสอบว่าค่าของตัวแปรในสแต็กเธรดจะเหมือนกับค่าของตัวแปรในหน่วยความจำหรือไม่
เช่น:
ThreadSee คลาสสาธารณะ {// เธรด T1 จะดำเนินการที่สอดคล้องกันตามค่าของธงและเธรดหลักจะเปลี่ยนค่าของ T1 Public Static Void Main (String [] args) พ่น InterruptedException {Threadtest th = new Threadtest (); เธรด t1 = เธรดใหม่ (th); t1.start (); Thread.sleep (1,000); th.changeflag (); Thread.sleep (2000); System.out.println (th.getFlag ()); }} คลาส Threadtest ใช้งาน unnable {// เมื่อเธรดเข้าถึงตัวแปรมันจะโหลดลงในสแต็กเธรดที่สอดคล้องกัน การดำเนินการแต่ละครั้งจะต้องได้รับข้อมูลล่าสุดในหน่วยความจำส่วนตัวที่ผันผวนของหน่วยความจำ stopflag; @Override โมฆะสาธารณะเรียกใช้ () {int i = 0; ในขณะที่ (! stopflag) {i ++; System.out.println ("=="+thread.currentthread (). getName ()); } system.out.println ("เธรดเสร็จ:"+i); } โมฆะสาธารณะ ChangeFlag () {this.stopflag = true; System.out.println (thread.currentthread (). getName ()+"*********"); } บูลีนสาธารณะ getFlag () {return stopFlag; - หากรหัสข้างต้นถูกลบออกไปมันจะดำเนินการต่อไปในการวนซ้ำที่ตายแล้ว
แต่ความผันผวนไม่สามารถรับประกันการซิงโครไนซ์แบบเธรดที่ปลอดภัย
เช่น:
ThreadSave คลาสสาธารณะใช้งาน Runnable {Static Threadsave Sync = new Threadsave (); Int ผันผวนแบบคงที่ j = 0; // ล็อคล็อค = ใหม่ reentrantlock (); โมฆะสาธารณะ inscane () {// lock.lock (); สำหรับ (int i = 0; i <10000000; i ++) {j ++; } // lock.unlock (); } @Override โมฆะสาธารณะ Run () {inscane (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น InterruptedException {เธรด t1 = เธรดใหม่ (ซิงค์); เธรด t2 = เธรดใหม่ (ซิงค์); t1.start (); t2.start (); t1.join (); t2.join (); System.out.println (J); - ผลลัพธ์ของการดำเนินการตามรหัสข้างต้นไม่คาดว่าจะเป็นปี 20000000
เนื่องจากสำหรับตัวแปรที่แก้ไขโดยความผันผวนเครื่องเสมือน JVM จะมั่นใจได้ว่าค่าที่โหลดจากหน่วยความจำหลักไปยังหน่วยความจำการทำงานของเธรดเป็นล่าสุด
ตัวอย่างเช่นหากเธรด 1 และเธรด 2 กำลังดำเนินการสแต็กเธรดและหน่วยความจำหลักอ่านและโหลดการดำเนินการและพบว่าค่าของการนับในหน่วยความจำหลักคือ 5 จากนั้นค่าล่าสุดจะถูกโหลด หลังจากการนับจำนวนเธรด 1 ฮีปได้รับการแก้ไขแล้วมันจะถูกเขียนลงในหน่วยความจำหลักและตัวแปรนับในหน่วยความจำหลักจะกลายเป็น 6;
เนื่องจากเธรด 2 ได้ดำเนินการอ่านและโหลดแล้วหลังจากดำเนินการค่าตัวแปรของจำนวนหน่วยความจำหลักจะได้รับการปรับปรุงเป็น 6;
สิ่งนี้ทำให้เกิดขึ้นพร้อมกันหลังจากสองเธรดได้รับการแก้ไขด้วยคำหลักที่ผันผวนในเวลา
โดยสรุป:
ความผันผวน จะตรวจสอบให้แน่ใจว่าเธรดดำเนินการที่ตรวจสอบว่าค่าตัวแปรของสแต็กเธรดปัจจุบันนั้นเหมือนกับค่าข้อมูลในหน่วยความจำหลักนั่นคือทั้งหมด ล็อคหรือ ซิงโครไนซ์ จะช่วยให้มั่นใจได้ว่ามีเพียงเธรดเดียวเท่านั้นที่จะเข้าสู่วิธีการในช่วงเวลาหนึ่งดังนั้นจึงมั่นใจได้ว่าจะมีความปลอดภัยจากด้าย
ดังนั้นหากหลายเธรดแก้ไขตัวแปรระเหยง่ายแสดงว่าไม่มีความหมายเชิงตรรกะจริง หากเธรดแก้ไขค่าตัวแปรของเธรดอื่น ๆ ที่ขึ้นอยู่กับการปรับเปลี่ยนมันจะเป็นประโยชน์ในเวลานี้
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน