ตัวแปรผันผวนให้การมองเห็นเธรดและไม่รับประกันความปลอดภัยของเธรดและอะตอม
ทัศนวิสัยของเธรดคืออะไร:
ล็อคมีคุณสมบัติหลักสองประการคือการยกเว้นและการมองเห็นซึ่งกันและกัน การยกเว้นซึ่งกันและกันหมายความว่ามีเพียงเธรดเดียวเท่านั้นที่สามารถถือล็อคที่เฉพาะเจาะจงได้ในแต่ละครั้งดังนั้นคุณสมบัตินี้สามารถใช้ในการใช้โปรโตคอลการเข้าถึงที่ประสานงานสำหรับข้อมูลที่ใช้ร่วมกันเพื่อให้เธรดเพียงหนึ่งเดียวสามารถใช้ข้อมูลที่ใช้ร่วมกันได้ในแต่ละครั้ง การมองเห็นมีความซับซ้อนมากขึ้นเล็กน้อยและจะต้องตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงข้อมูลที่ใช้ร่วมกันก่อนที่จะปล่อยล็อคสามารถมองเห็นได้ในเธรดอื่นที่ได้รับการล็อค - โดยไม่ต้องรับประกันการมองเห็นนี้โดยกลไกการซิงโครไนซ์
ดู ความหมายของความผันผวน :
ความผันผวนนั้นเทียบเท่ากับการใช้งานที่อ่อนแอของการซิงโครไนซ์ซึ่งหมายความว่าการใช้ความหมายแบบซิงโครไนซ์ที่มีความผันผวน แต่ไม่มีกลไกการล็อค ช่วยให้มั่นใจได้ว่าการอัปเดตฟิลด์ที่ผันผวนแจ้งเธรดอื่น ๆ ในวิธีที่คาดเดาได้
ความผันผวนมีความหมายต่อไปนี้:
(1) รูปแบบการจัดเก็บ Java จะไม่จัดลำดับการดำเนินการของคำสั่ง valatile ใหม่: สิ่งนี้ทำให้มั่นใจได้ว่าการดำเนินการเกี่ยวกับตัวแปรผันผวนจะดำเนินการตามลำดับที่คำสั่งปรากฏขึ้น
(2) ตัวแปรผันผวนจะไม่ถูกแคชในการลงทะเบียน (เฉพาะเธรดที่มองเห็นได้) หรือสถานที่อื่น ๆ ที่ไม่สามารถมองเห็นได้ของ CPU ผลลัพธ์ของตัวแปรผันผวนจะถูกอ่านจากหน่วยความจำหลักเสมอทุกครั้ง กล่าวอีกนัยหนึ่งสำหรับการปรับเปลี่ยนตัวแปรระเหยง่ายเธรดอื่น ๆ จะมองเห็นได้เสมอและพวกเขาไม่ได้ใช้ตัวแปรภายในสแต็กเธรด นั่นคือในกฎหมายที่เกิดขึ้นก่อนหน้านี้หลังจากเขียนตัวแปร valatile การดำเนินการอ่านที่ตามมาใด ๆ สามารถเข้าใจได้เพื่อดูผลลัพธ์ของการดำเนินการเขียนนี้
แม้ว่าลักษณะของตัวแปรผันผวนจะดี แต่ความผันผวนไม่สามารถรับประกันความปลอดภัยของเธรดได้ กล่าวคือการทำงานของสนามผันผวนไม่ใช่อะตอม ตัวแปรผันผวนสามารถรับประกันการมองเห็นได้เท่านั้น (เธรดอื่น ๆ สามารถเข้าใจผลลัพธ์หลังจากเห็นการเปลี่ยนแปลงนี้หลังจากแก้ไขเธรดหนึ่ง) เพื่อให้แน่ใจว่าอะตอมคุณสามารถล็อคได้เท่านั้น!
หลักการสำหรับการใช้ความผันผวน:
สามหลักการสำหรับการใช้ตัวแปรผันผวน:
(1) ตัวแปรการเขียนไม่ได้ขึ้นอยู่กับค่าของตัวแปรนี้หรือมีเพียงเธรดเดียวเท่านั้นที่แก้ไขตัวแปรนี้
(2) สถานะของตัวแปรไม่จำเป็นต้องมีส่วนร่วมในข้อ จำกัด ที่ไม่เปลี่ยนแปลงกับตัวแปรอื่น ๆ
(3) ไม่จำเป็นต้องล็อคตัวแปร
ในความเป็นจริงเงื่อนไขเหล่านี้บ่งชี้ว่าค่าที่ถูกต้องเหล่านี้สามารถเขียนไปยังตัวแปรระเหยได้นั้นเป็นอิสระจากสถานะของโปรแกรมใด ๆ รวมถึงสถานะปัจจุบันของตัวแปร
จำกัด เงื่อนไขแรกป้องกันไม่ให้ตัวแปรระเหยง่ายถูกใช้เป็นตัวนับเธรดที่ปลอดภัย แม้ว่าการดำเนินการที่เพิ่มขึ้น (x ++) ดูเหมือนการดำเนินการแยกต่างหาก แต่จริง ๆ แล้วเป็นการดำเนินการรวมกันซึ่งประกอบด้วยลำดับของการดำเนินการอ่าน-ดัดแปลง-เขียนที่ต้องดำเนินการทางอะตอมและความผันผวนไม่สามารถให้คุณสมบัติอะตอมที่จำเป็นได้ การใช้การดำเนินการที่ถูกต้องต้องรักษาค่าของค่าคงที่ x ในระหว่างการดำเนินการซึ่งไม่สามารถทำได้ด้วยตัวแปรผันผวน (อย่างไรก็ตามหากมีการปรับค่าที่จะเขียนจากเธรดเดียวเท่านั้นเงื่อนไขแรกสามารถละเว้นได้)
สถานการณ์การเขียนโปรแกรมส่วนใหญ่ขัดแย้งกับหนึ่งในสามเงื่อนไขเหล่านี้ทำให้ตัวแปรผันผวนไม่สามารถใช้ได้กับความปลอดภัยของเธรดในระดับสากล รายการ 1 แสดงคลาสช่วงตัวเลขที่ไม่ปลอดภัย มันมีค่าคงที่ - ขอบเขตล่างมักจะน้อยกว่าหรือเท่ากับขอบเขตบน
ใช้ความผันผวนอย่างถูกต้อง:
โหมด #1: สถานะสถานะ
บางทีข้อมูลจำเพาะของการใช้ตัวแปรผันผวนอาจใช้ธงสถานะบูลีนเพื่อระบุว่าเหตุการณ์ที่สำคัญเกิดขึ้นครั้งเดียวเกิดขึ้นเช่นการเริ่มต้นการเริ่มต้นหรือขอเวลาหยุดทำงาน
แอปพลิเคชันจำนวนมากรวมถึงโครงสร้างการควบคุมในรูปแบบของ "ดำเนินการบางอย่างเมื่อโปรแกรมไม่พร้อมที่จะหยุด" ดังที่แสดงในรายการ 2:
รายการ 2. ใช้ตัวแปรผันผวนเป็นสถานะสถานะ
บูลีนที่ผันผวน shutdownrequested; …การปิดช่องว่างสาธารณะ () {shutdownRequested = true; } โมฆะสาธารณะ Dowork () {ในขณะที่ (! shutdownRequested) {// do stuff}}มีความเป็นไปได้สูงที่วิธีการปิด () จะถูกเรียกจากนอกลูป - เช่นในเธรดอื่น - ดังนั้นจึงต้องดำเนินการซิงโครไนซ์บางชนิดเพื่อให้แน่ใจว่าการมองเห็นตัวแปรปิดการเรียกร้องถูกนำไปใช้อย่างถูกต้อง (อาจถูกเรียกจาก JMX Listener, Operation Listener in GUI Event Thread ผ่าน RMI ผ่านบริการเว็บ ฯลฯ ) อย่างไรก็ตามการเขียนลูปที่มีบล็อกที่ซิงโครไนซ์นั้นลำบากกว่าการเขียนด้วยธงสถานะผันผวนที่แสดงในรายการ 2 เนื่องจากความผันผวนทำให้การเข้ารหัสง่ายขึ้นและสถานะสถานะไม่ได้ขึ้นอยู่กับสถานะอื่น ๆ ภายในโปรแกรมจึงเหมาะสำหรับความผันผวนที่นี่
คุณสมบัติทั่วไปของแท็กสถานะประเภทนี้คือมักจะมีการเปลี่ยนแปลงของรัฐเพียงครั้งเดียว ธง shutdownrequested จะถูกแปลงจากเท็จเป็นความจริงและโปรแกรมหยุด รูปแบบนี้สามารถขยายไปยังสถานะสถานะของการเปลี่ยนแปลงกลับไปกลับมา แต่สามารถขยายได้ก็ต่อเมื่อไม่มีการสังเกตการเปลี่ยนแปลง (จากเท็จเป็นความจริงแล้วเป็นเท็จ) นอกจากนี้จำเป็นต้องใช้กลไกการแปลงสถานะอะตอมบางอย่างเช่นตัวแปรอะตอม
โหมด #2: สิ่งพิมพ์ที่ปลอดภัยเพียงครั้งเดียว
การขาดการซิงโครไนซ์สามารถนำไปสู่การมองเห็นที่ไม่สามารถทำได้ซึ่งทำให้ยากต่อการกำหนดว่าจะเขียนการอ้างอิงวัตถุแทนที่จะเป็นค่าดั้งเดิม ในกรณีที่ไม่มีการซิงโครไนซ์ค่าที่อัปเดตอ้างอิงโดยวัตถุ (เขียนโดยเธรดอื่น) อาจพบได้และค่าเก่าของสถานะของวัตถุนั้นมีอยู่พร้อมกัน (นี่คือสาเหตุที่แท้จริงของปัญหาการล็อคแบบตรวจสอบสองครั้งที่มีชื่อเสียงซึ่งการอ้างอิงวัตถุถูกอ่านโดยไม่ต้องซิงโครไนซ์ส่งผลให้ปัญหาที่คุณอาจเห็นการอ้างอิงที่อัปเดต แต่ยังเห็นวัตถุที่สร้างขึ้นไม่สมบูรณ์ผ่านการอ้างอิงนั้น)
เทคนิคหนึ่งในการใช้การเผยแพร่วัตถุที่ปลอดภัยคือการกำหนดการอ้างอิงวัตถุเป็นประเภทที่ผันผวน รายการ 3 แสดงตัวอย่างที่เธรดพื้นหลังโหลดข้อมูลบางส่วนจากฐานข้อมูลระหว่างการเริ่มต้น รหัสอื่น ๆ เมื่อพวกเขาสามารถใช้ข้อมูลนี้ได้ตรวจสอบว่ามีการเผยแพร่ก่อนการใช้งานหรือไม่
รายการ 3. การใช้ตัวแปรผันผวนสำหรับการเปิดตัวที่ปลอดภัยเพียงครั้งเดียว
พื้นหลังชั้นเรียนสาธารณะ floobleloader {สาธารณะระเหยได้ฟลอฟฟลอฟฟูลเบิล; public void initinbackground () {// ทำสิ่งต่าง ๆ มากมาย theflooble = new flooble (); // นี่เป็นเพียงการเขียนถึง TheFlooble}} คลาสสาธารณะ Someotherclass {Public Void Dowork () {ในขณะที่ (จริง) {// ทำบางสิ่งบางอย่าง… // ใช้ flooble แต่ถ้ามันพร้อมถ้า (floobleloader.theflooble! = null) -หากการอ้างอิง Theflooble ไม่ใช่ประเภทที่ผันผวนโค้ดใน Dowork () จะได้รับการฟลอเบิลที่สร้างขึ้นอย่างไม่สมบูรณ์เมื่อมันไม่ได้ทำการตรวจหา Theflooble
เงื่อนไขที่จำเป็นสำหรับรูปแบบนี้คือวัตถุที่เผยแพร่จะต้องมีความปลอดภัยด้ายหรือวัตถุที่ไม่เปลี่ยนรูปที่ถูกต้อง การอ้างอิงของประเภทความผันผวนเพื่อให้แน่ใจว่าการมองเห็นแบบฟอร์มสิ่งพิมพ์ของวัตถุ แต่จำเป็นต้องมีการซิงโครไนซ์เพิ่มเติมหากสถานะของวัตถุจะเปลี่ยนหลังจากการตีพิมพ์
รูปแบบ #3: การสังเกตอิสระ
อีกโหมดง่าย ๆ ในการใช้ความผันผวนอย่างปลอดภัยคือการ "ปล่อย" การสังเกตอย่างสม่ำเสมอสำหรับการใช้งานภายในของโปรแกรม ตัวอย่างเช่นสมมติว่ามีเซ็นเซอร์โดยรอบที่สามารถตรวจจับอุณหภูมิแวดล้อมได้ เธรดพื้นหลังอาจอ่านเซ็นเซอร์ทุกสองสามวินาทีและอัปเดตตัวแปรผันผวนที่มีเอกสารปัจจุบัน จากนั้นเธรดอื่น ๆ สามารถอ่านตัวแปรนี้เพื่อให้สามารถดูค่าอุณหภูมิล่าสุดได้ตลอดเวลา
แอปพลิเคชั่นอื่นที่ใช้โหมดนี้คือการรวบรวมสถิติของโปรแกรม รายการ 4 แสดงให้เห็นว่ากลไกการรับรองความถูกต้องจดจำชื่อของผู้ใช้ที่เข้าสู่ระบบเป็นครั้งสุดท้ายได้อย่างไร ทำซ้ำการอ้างอิงล่าสุดเพื่อเผยแพร่ค่าสำหรับส่วนอื่น ๆ ของโปรแกรม
รายการ 4. การใช้ตัวแปรผันผวนสำหรับการเผยแพร่การสังเกตอิสระหลายครั้ง
ผู้ใช้ระดับสาธารณะ userManager {สตริงที่ผันผวนสาธารณะ การรับรองความถูกต้องของบูลีนสาธารณะ (ผู้ใช้สตริง, รหัสผ่านสตริง) {บูลีนถูกต้อง = passwordisvalid (ผู้ใช้, รหัสผ่าน); if (ถูกต้อง) {ผู้ใช้ u = ผู้ใช้ใหม่ (); activeUsers.add (u); LastUser = ผู้ใช้; } return ถูกต้อง; -โหมดนี้เป็นส่วนขยายของโหมดก่อนหน้า การเผยแพร่ค่าที่แน่นอนสำหรับการใช้งานที่อื่นในโปรแกรม แต่แตกต่างจากการเผยแพร่เหตุการณ์ครั้งเดียวมันเป็นชุดของกิจกรรมอิสระ รูปแบบนี้ต้องการให้ค่าที่เผยแพร่นั้นถูกต้องและไม่เปลี่ยนรูป - นั่นคือสถานะของมูลค่าจะไม่เปลี่ยนแปลงหลังจากการตีพิมพ์ รหัสที่ใช้ค่านี้จะต้องชัดเจนว่าค่าอาจเปลี่ยนแปลงได้ตลอดเวลา
โหมด #4: โหมด "ผันผวนถั่ว"
รูปแบบถั่วผันผวนเหมาะสำหรับเฟรมเวิร์กที่ใช้ Javabeans เป็น "โครงสร้างเกียรติ" ในรูปแบบถั่วผันผวน javabeans ถูกใช้เป็นชุดของภาชนะบรรจุที่มีคุณสมบัติอิสระของวิธี getter และ/หรือ setter หลักการพื้นฐานของรูปแบบถั่วผันผวนคือเฟรมเวิร์กจำนวนมากให้ภาชนะสำหรับผู้ถือข้อมูลที่ผันผวน (เช่น HTTPSESSION) แต่วัตถุที่วางไว้ในภาชนะเหล่านี้จะต้องมีความปลอดภัย
ในโหมดถั่วผันผวนสมาชิกข้อมูลทั้งหมดของ javabean เป็นประเภทที่ผันผวนและวิธีการ getter และ setter จะต้องเป็นเรื่องธรรมดามาก - พวกเขาไม่สามารถมีตรรกะใด ๆ ยกเว้นเพื่อให้ได้หรือตั้งค่าคุณสมบัติที่สอดคล้องกัน นอกจากนี้สำหรับสมาชิกข้อมูลที่อ้างอิงโดยวัตถุวัตถุที่อ้างอิงจะต้องถูกต้องและไม่เปลี่ยนรูป (สิ่งนี้จะห้ามคุณสมบัติที่มีค่าอาร์เรย์เพราะเมื่อการอ้างอิงอาร์เรย์ถูกประกาศว่าเป็นความผันผวนเฉพาะการอ้างอิงและไม่ใช่อาร์เรย์เท่านั้นที่มีความหมายระเหย) สำหรับตัวแปรผันผวนใด ๆ ค่าคงที่หรือข้อ จำกัด ไม่สามารถมีคุณสมบัติ javabean ตัวอย่างในรายการ 5 Show Javabeans ที่ยึดติดกับรูปแบบถั่วผันผวน:
โหมด #4: โหมด "ผันผวนถั่ว"
@ThreadSafe บุคคลระดับสาธารณะ {สตริงผันผวนส่วนตัว FIRSTNAME; สตริงผันผวนส่วนตัวนามสกุล; อายุ int ผันผวนส่วนตัว; สตริงสาธารณะ getFirstName () {return firstName; } สตริงสาธารณะ getLaStName () {return lastName; } public int getage () {return Age; } โมฆะสาธารณะ setFirstName (String firstName) {this.firstName = firstName; } โมฆะสาธารณะ setLastName (สตริงนามสกุล) {this.lastName = LastName; } การตั้งค่าโมฆะสาธารณะ (อายุ int) {this.age = อายุ; -โหมดขั้นสูงของความผันผวน
รูปแบบที่อธิบายไว้ในส่วนก่อนหน้านี้ครอบคลุมกรณีการใช้งานพื้นฐานส่วนใหญ่และการใช้ความผันผวนในรูปแบบเหล่านี้มีประโยชน์และง่ายมาก ส่วนนี้แนะนำโหมดขั้นสูงที่ผันผวนจะให้ประสิทธิภาพหรือความสามารถในการปรับขนาดได้
โหมดขั้นสูงของแอปพลิเคชันที่ผันผวนนั้นเปราะบางมาก ดังนั้นสมมติฐานจะต้องได้รับการพิสูจน์อย่างรอบคอบและรูปแบบเหล่านี้ถูกห่อหุ้มอย่างเคร่งครัดเพราะแม้การเปลี่ยนแปลงที่เล็กมากสามารถทำให้รหัสของคุณเสียหายได้! ในทำนองเดียวกันเหตุผลในการใช้กรณีการใช้งานที่ผันผวนขั้นสูงมากขึ้นคือมันสามารถปรับปรุงประสิทธิภาพเพื่อให้มั่นใจว่าคุณกำหนดว่าคุณต้องได้รับประโยชน์ด้านประสิทธิภาพนี้ก่อนที่คุณจะเริ่มใช้รูปแบบขั้นสูง มีการแลกเปลี่ยนในรูปแบบเหล่านี้การให้ความสามารถในการอ่านหรือการบำรุงรักษาเพื่อแลกกับการเพิ่มประสิทธิภาพที่เป็นไปได้-หากคุณไม่ต้องการการปรับปรุงประสิทธิภาพ (หรือไม่สามารถพิสูจน์ได้ว่าคุณต้องการมันผ่านโปรแกรมทดสอบที่เข้มงวด) จากนั้นก็น่าจะเป็นข้อตกลงที่ไม่ดีเพราะคุณจะสูญเสียเงินน้อยลง
โหมด #5: กลยุทธ์การอ่าน-เขียน-เขียนด้วยค่าใช้จ่ายต่ำ
จนถึงตอนนี้คุณควรเข้าใจว่าความผันผวนนั้นไม่สามารถใช้เคาน์เตอร์ได้ เนื่องจาก ++ X เป็นการรวมกันอย่างง่ายของการดำเนินการสามครั้ง (อ่านเพิ่มจัดเก็บ) หากหลายเธรดเกิดขึ้นเพื่อพยายามดำเนินการเพิ่มขึ้นบนเคาน์เตอร์ผันผวนในเวลาเดียวกันค่าที่อัปเดตอาจหายไป
อย่างไรก็ตามหากการดำเนินการอ่านเป็นมากกว่าการดำเนินการเขียนคุณสามารถใช้ตัวแปรล็อคภายในและตัวแปรผันผวนเพื่อลดค่าใช้จ่ายของเส้นทางรหัสสาธารณะ เคาน์เตอร์ที่ปลอดภัยจากเธรดที่แสดงในรายการ 6 ใช้การซิงโครไนซ์เพื่อให้แน่ใจว่าการดำเนินการที่เพิ่มขึ้นนั้นเป็นอะตอมและผันผวนเพื่อให้แน่ใจว่าการมองเห็นผลลัพธ์ปัจจุบัน วิธีนี้สามารถบรรลุประสิทธิภาพที่ดีขึ้นหากการอัปเดตไม่บ่อยนักเนื่องจากค่าใช้จ่ายของเส้นทางการอ่านนั้นเกี่ยวข้องกับการดำเนินการอ่านที่ผันผวนเท่านั้นซึ่งมักจะดีกว่าค่าใช้จ่ายของการล็อคที่ปราศจากการแข่งขัน
รายการ 6. ใช้ความผันผวนและซิงโครไนซ์เพื่อให้ได้ "ล็อคการอ่านค่าใช้จ่ายที่ต่ำกว่า"
@ThreadSafe คลาสสาธารณะ Cheesycounter {// ใช้เคล็ดลับการอ่านคำแนะนำการอ่าน-เขียนราคาถูก // การดำเนินการกลายพันธุ์ทั้งหมดจะต้องทำด้วย 'ล็อคนี้' ที่จัดขึ้น @GuardedBy ("นี้") ค่า int ที่ผันผวนส่วนตัว; public int getValue () {ค่าคืน; } public synchronized int cuprement () {return value ++; -เหตุผลที่เทคนิคนี้เรียกว่า เนื่องจากการดำเนินการเขียนในตัวอย่างนี้ละเมิดเงื่อนไขแรกของการใช้ความผันผวนตัวนับจึงไม่สามารถนำไปใช้งานได้อย่างปลอดภัยด้วยความผันผวน - คุณต้องใช้ล็อค อย่างไรก็ตามคุณสามารถใช้ความผันผวนในการดำเนินการอ่านเพื่อให้แน่ใจว่าการมองเห็นค่าปัจจุบันดังนั้นคุณสามารถใช้ล็อคเพื่อทำการเปลี่ยนแปลงทั้งหมดและอ่านอย่างเดียวด้วยความผันผวน ในหมู่พวกเขาล็อคอนุญาตให้เพียงหนึ่งเธรดเพื่อเข้าถึงค่าในแต่ละครั้งและความผันผวนช่วยให้หลายเธรดสามารถดำเนินการอ่านได้ ดังนั้นเมื่อใช้ความผันผวนเพื่อให้แน่ใจว่าเส้นทางรหัสถูกอ่านมันจะมีการแชร์มากกว่าการใช้ล็อคเพื่อเรียกใช้เส้นทางรหัสทั้งหมด - เช่นเดียวกับการดำเนินการอ่าน - เขียน อย่างไรก็ตามโปรดจำไว้ว่าจุดอ่อนของโมเดลนี้อยู่ในใจ: หากแอปพลิเคชันพื้นฐานที่สุดของโมเดลนี้อยู่นอกเหนือมันจะกลายเป็นเรื่องยากมากที่จะรวมกลไกการซิงโครไนซ์การแข่งขันทั้งสองนี้เข้าด้วยกัน
เกี่ยวกับคำแนะนำการจัดลำดับใหม่และกฎที่เกิดขึ้นก่อนหน้านี้
1. ให้สั่งซื้อใหม่
ข้อกำหนดภาษา Java กำหนดว่าเธรด JVM รักษาความหมายตามลำดับภายในนั่นคือตราบใดที่ผลลัพธ์สุดท้ายของโปรแกรมนั้นเทียบเท่ากับผลลัพธ์ในสภาพแวดล้อมที่เข้มงวดลำดับการดำเนินการตามคำสั่งอาจไม่สอดคล้องกับลำดับของรหัส กระบวนการนี้มีการจัดลำดับใหม่โดยคำสั่ง ความสำคัญของการสั่งซื้อใหม่คือ JVM สามารถจัดลำดับคำแนะนำเครื่องใหม่ได้อย่างเหมาะสมตามลักษณะของโปรเซสเซอร์ (ระบบแคชหลายระดับของ CPU โปรเซสเซอร์หลายคอร์ ฯลฯ ) เพื่อให้คำแนะนำของเครื่องมีความสอดคล้องกับลักษณะการดำเนินการของ CPU และเพิ่มประสิทธิภาพของเครื่อง
แบบจำลองที่ง่ายที่สุดสำหรับการดำเนินการโปรแกรมคือการดำเนินการตามลำดับที่คำสั่งปรากฏขึ้นซึ่งเป็นอิสระจาก CPU ที่ดำเนินการตามคำแนะนำเพื่อให้มั่นใจว่าการพกพาของคำสั่งในระดับที่ยิ่งใหญ่ที่สุด คำศัพท์ระดับมืออาชีพสำหรับรุ่นนี้เรียกว่าโมเดลความสอดคล้องตามลำดับ อย่างไรก็ตามระบบคอมพิวเตอร์ที่ทันสมัยและสถาปัตยกรรมโปรเซสเซอร์ไม่รับประกันสิ่งนี้ (เนื่องจากการกำหนดเทียมไม่สามารถรับประกันการปฏิบัติตามลักษณะการประมวลผล CPU ได้เสมอ)
2. Appens-ก่อนกฎ
รูปแบบการจัดเก็บ Java มีหลักการที่เกิดขึ้นก่อนนั่นคือถ้า Action B ต้องการเห็นผลการดำเนินการของการกระทำ A (ไม่ว่า A/B จะถูกดำเนินการในเธรดเดียวกัน) แล้ว A/B จำเป็นต้องตอบสนองความสัมพันธ์ที่เกิดขึ้นก่อน
ก่อนที่จะแนะนำกฎที่เกิดขึ้นก่อนหน้านี้แนะนำแนวคิด: การกระทำของ JMM (การกระทำของโมเดล Java Memeory), Java เก็บการกระทำของแบบจำลอง การกระทำรวมถึง: อ่านและเขียนตัวแปรการล็อคการตรวจสอบและการล็อคการปล่อยเธรดเริ่มต้น () และเข้าร่วม () ล็อคจะถูกกล่าวถึงในภายหลัง
เกิดขึ้น-ก่อนหน้ากฎที่สมบูรณ์:
(1) การกระทำแต่ละครั้งในเธรดเดียวกันเกิดขึ้นก่อนการกระทำใด ๆ ที่ปรากฏขึ้นหลังจากนั้น
(2) การปลดล็อคจอภาพจะเกิดขึ้นก่อนที่จะล็อคแต่ละครั้งต่อมาบนจอภาพเดียวกัน
(3) การเขียนการดำเนินการไปยังฟิลด์ที่ผันผวนเกิดขึ้นก่อนการดำเนินการอ่านแต่ละครั้งในแต่ละฟิลด์เดียวกัน
(4) การโทรไปยังเธรดเริ่มต้น () จะเกิดขึ้นก่อนการกระทำในเธรดเริ่มต้น
(5) การกระทำทั้งหมดในเธรดเกิดขึ้นก่อนที่จะตรวจสอบในเธรดอื่นเพื่อสิ้นสุดเธรดนี้หรือส่งคืนใน thread.join () หรือ thread.isalive () == False
(6) หนึ่งเธรด A การเรียกอินเตอร์รัปต์ () ของเธรดอื่น B เกิดขึ้นก่อนเมื่อเธรด A พบว่า B ถูกขัดจังหวะโดย A (B พ่นข้อยกเว้นหรือตรวจจับ b isinterrupted () หรือขัดจังหวะ ())
(7) จุดสิ้นสุดของตัวสร้างวัตถุเกิดขึ้นก่อนและจุดเริ่มต้นของ finalizer ของวัตถุ
(8) หากการกระทำเกิดขึ้นก่อนหน้านี้อยู่ในการดำเนินการ b และการกระทำ b เกิดขึ้นก่อนและการกระทำ c การกระทำที่เกิดขึ้นก่อนหน้านี้คือการดำเนินการ C.
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ ฉันจะแนะนำให้คุณที่นี่ ฉันหวังว่ามันจะเป็นประโยชน์สำหรับคุณที่จะเรียนรู้และเข้าใจตัวแปรผันผวนใน Java