อะไรคือความแตกต่างระหว่างอะตอม / ระเหย / ซิงโครไนซ์?


297

อะตอม / ระเหย / ซิงโครไนซ์ทำงานอย่างไรภายใน

ความแตกต่างระหว่างบล็อครหัสต่อไปนี้คืออะไร?

รหัส 1

private int counter;

public int getNextUniqueIndex() {
    return counter++; 
}

รหัส 2

private AtomicInteger counter;

public int getNextUniqueIndex() {
    return counter.getAndIncrement();
}

รหัส 3

private volatile int counter;

public int getNextUniqueIndex() {
    return counter++; 
}

ไม่volatileทำงานในลักษณะดังต่อไปนี้หรือไม่? คือ

volatile int i = 0;
void incIBy5() {
    i += 5;
}

เทียบเท่ากับ

Integer i = 5;
void incIBy5() {
    int temp;
    synchronized(i) { temp = i }
    synchronized(i) { i = temp + 5 }
}

ฉันคิดว่าสองกระทู้ไม่สามารถเข้าบล็อกที่ซิงโครไนซ์ได้ในเวลาเดียวกัน ... ฉันถูกไหม หากเป็นจริงแล้ววิธีการatomic.incrementAndGet()ทำงานโดยไม่มีsynchronized? และมันปลอดภัยไหม?

อะไรคือความแตกต่างระหว่างการอ่านและการเขียนภายในกับตัวแปรที่ผันแปรได้ / ตัวแปรอะตอมมิก? ฉันอ่านในบางบทความว่าเธรดมีสำเนาโลคัลของตัวแปร - นั่นคืออะไร


5
นั่นทำให้คำถามจำนวนมากทั้งรหัสที่ไม่ได้รวบรวม บางทีคุณควรอ่านหนังสือดีๆเช่น Java Concurrency in Practice
JB Nizet

4
@JBNizet คุณถูก !!! ฉันมีหนังสือเล่มนั้นมันไม่มีแนวคิดแบบย่อ ๆ ของอะตอมและฉันไม่ได้รับแนวคิดบางอย่างของเรื่องนั้น จากคำสาปมันเป็นความผิดพลาดของฉันไม่ใช่ของผู้เขียน
hardik

4
คุณไม่ต้องสนใจว่าจะมีการใช้งานอย่างไร (และแตกต่างกันไปตามระบบปฏิบัติการ) สิ่งที่คุณต้องเข้าใจคือสัญญา: ค่านั้นเพิ่มขึ้นแบบอะตอมและเธรดอื่น ๆ ทั้งหมดจะรับประกันว่าจะเห็นค่าใหม่
JB Nizet

คำตอบ:


392

คุณกำลังถามว่าพวกเขาทำงานอย่างไรภายในโดยเฉพาะดังนั้นคุณอยู่ที่นี่:

ไม่มีการซิงโครไนซ์

private int counter;

public int getNextUniqueIndex() {
  return counter++; 
}

โดยทั่วไปจะอ่านค่าจากหน่วยความจำเพิ่มขึ้นและกลับไปสู่หน่วยความจำ สิ่งนี้ใช้ได้ในเธรดเดียว แต่ทุกวันนี้ในยุคของมัลติคอร์มัลติซีพียูแคชหลายระดับจะทำงานไม่ถูกต้อง ก่อนอื่นจะแนะนำสภาพการแข่งขัน (หลายกระทู้สามารถอ่านค่าในเวลาเดียวกัน) แต่ยังมีปัญหาการมองเห็น ค่าอาจถูกเก็บไว้ในหน่วยความจำซีพียู " ท้องถิ่น " (บางแคช) และไม่สามารถมองเห็นได้สำหรับซีพียู / คอร์อื่น (และ - เธรด) นี่คือสาเหตุที่หลายคนอ้างถึงสำเนาของตัวแปรในเครื่อง มันไม่ปลอดภัยมาก พิจารณารหัสการหยุดเธรดที่เป็นที่นิยม แต่ใช้งานไม่ได้นี้:

private boolean stopped;

public void run() {
    while(!stopped) {
        //do some work
    }
}

public void pleaseStop() {
    stopped = true;
}

เพิ่มvolatileไปที่stoppedตัวแปรและใช้งานได้ดี - หากเธรดอื่น ๆ แก้ไขstoppedตัวแปรผ่านpleaseStop()วิธีการคุณจะรับประกันว่าจะเห็นการเปลี่ยนแปลงนั้นทันทีในwhile(!stopped)ลูปของเธรดการทำงาน BTW นี้ไม่ได้เป็นวิธีที่ดีที่จะขัดขวางด้ายทั้งดู: วิธีการหยุดด้ายที่ใช้ตลอดไปโดยไม่ต้องใช้ใด ๆและหยุดด้ายเฉพาะจาวา

AtomicInteger

private AtomicInteger counter = new AtomicInteger();

public int getNextUniqueIndex() {
  return counter.getAndIncrement();
}

AtomicIntegerใช้ระดับ CAS ( เปรียบเทียบและ-swap ) การดำเนินงานในระดับต่ำ CPU (ไม่จำเป็นต้องประสาน!) พวกเขาช่วยให้คุณสามารถปรับเปลี่ยนตัวแปรโดยเฉพาะอย่างยิ่งเฉพาะในกรณีที่มูลค่าปัจจุบันเท่ากับสิ่งอื่น (และถูกส่งกลับประสบความสำเร็จ) ดังนั้นเมื่อคุณรันgetAndIncrement()มันจะทำงานเป็นวง (การใช้จริงที่ง่าย):

int current;
do {
  current = get();
} while(!compareAndSet(current, current + 1));

ดังนั้นโดยทั่วไป: อ่าน; พยายามเก็บค่าที่เพิ่มขึ้น หากไม่สำเร็จ (ค่าไม่เท่ากับcurrent) ให้อ่านและลองอีกครั้ง compareAndSet()จะดำเนินการในรหัสพื้นเมือง (งานประกอบ)

volatile โดยไม่ต้องประสาน

private volatile int counter;

public int getNextUniqueIndex() {
  return counter++; 
}

รหัสนี้ไม่ถูกต้อง มันแก้ไขปัญหาการมองเห็น ( volatileทำให้แน่ใจว่ากระทู้อื่น ๆ สามารถเห็นการเปลี่ยนแปลงที่เกิดขึ้นcounter) แต่ยังคงมีสภาพการแข่งขัน สิ่งนี้ได้รับการอธิบายหลาย ๆ ครั้ง: การเพิ่มขึ้นก่อน / หลังไม่ได้เป็นแบบอะตอม

ผลข้างเคียงเพียงอย่างเดียวของvolatileคือการ " ล้างข้อมูล " แคชเพื่อให้บุคคลอื่นทั้งหมดเห็นข้อมูลเวอร์ชันใหม่ที่สุด นี่เข้มงวดเกินไปในสถานการณ์ส่วนใหญ่ นั่นคือเหตุผลที่volatileไม่ได้เป็นค่าเริ่มต้น

volatile ไม่มีการประสาน (2)

volatile int i = 0;
void incIBy5() {
  i += 5;
}

ปัญหาเช่นเดียวกับข้างต้น แต่ยิ่งเลวร้ายลงเพราะไม่ได้เป็นi privateสภาพการแข่งขันยังคงมีอยู่ ทำไมถึงเป็นปัญหา? ถ้าพูดสองหัวข้อเรียกใช้รหัสนี้ไปพร้อม ๆ กันการส่งออกอาจจะมีหรือ+ 5 + 10อย่างไรก็ตามคุณรับประกันว่าจะเห็นการเปลี่ยนแปลง

อิสระหลายอย่าง synchronized

void incIBy5() {
  int temp;
  synchronized(i) { temp = i }
  synchronized(i) { i = temp + 5 }
}

แปลกใจที่รหัสนี้ไม่ถูกต้องเช่นกัน ความจริงมันผิดทั้งหมด ก่อนอื่นคุณกำลังทำการซิงโครไนซ์iซึ่งกำลังจะมีการเปลี่ยนแปลง (ยิ่งไปกว่านั้นiคือดึกดำบรรพ์ดังนั้นฉันเดาว่าคุณกำลังซิงโครไนซ์กับชั่วคราวที่Integerสร้างขึ้นผ่านออโต้บ็อกซ์ ... ) มีข้อบกพร่องอย่างสมบูรณ์ คุณสามารถเขียน:

synchronized(new Object()) {
  //thread-safe, SRSLy?
}

ไม่มีสองหัวข้อสามารถป้อนเดียวกันsynchronizedบล็อกที่มีการล็อคเดียวกัน ในกรณีนี้ (และในทำนองเดียวกันในรหัสของคุณ) วัตถุล็อคจะเปลี่ยนไปตามการดำเนินการทุกครั้งดังนั้นจึงsynchronizedไม่มีผล

แม้ว่าคุณจะใช้ตัวแปรสุดท้าย (หรือthis) สำหรับการซิงโครไนซ์ แต่รหัสก็ยังไม่ถูกต้อง สองเธรดสามารถอ่านiเพื่อtempซิงโครนัส (มีค่าเดียวกันในเครื่องtemp) จากนั้นเธรดแรกกำหนดค่าใหม่ให้กับi(พูดจาก 1 ถึง 6) และอีกอันหนึ่งทำสิ่งเดียวกัน (จาก 1 ถึง 6)

การซิงโครไนซ์ต้องครอบคลุมตั้งแต่การอ่านจนถึงการกำหนดค่า การซิงโครไนซ์ครั้งแรกของคุณไม่มีผลกระทบ (การอ่านintคืออะตอมมิก) และวินาทีเช่นกัน ในความคิดของฉันเหล่านี้เป็นรูปแบบที่ถูกต้อง:

void synchronized incIBy5() {
  i += 5 
}

void incIBy5() {
  synchronized(this) {
    i += 5 
  }
}

void incIBy5() {
  synchronized(this) {
    int temp = i;
    i = temp + 5;
  }
}

10
สิ่งเดียวที่ฉันเพิ่มคือ JVM คัดลอกค่าตัวแปรลงทะเบียนเพื่อดำเนินการกับพวกเขา ซึ่งหมายความว่าเธรดที่ทำงานบน CPU / core เดียวยังคงสามารถเห็นค่าที่แตกต่างกันสำหรับตัวแปรที่ไม่ลบเลือน
David Harkness

@thomasz: ซิงโครไนซ์AndSet (กระแส, กระแส + 1) ตรงกันหรือไม่? ถ้าไม่มากกว่าจะเกิดอะไรขึ้นเมื่อสองเธรดกำลังเรียกใช้เมธอดนี้ในเวลาเดียวกัน?
hardik

@ Hardik: compareAndSetเป็นเพียงเสื้อคลุมบาง ๆ เกี่ยวกับการทำงานของ CAS ฉันเข้าไปดูรายละเอียดในคำตอบของฉัน
Tomasz Nurkiewicz

1
@thomsasz: ตกลงฉันผ่านคำถามลิงค์นี้และตอบโดย jon skeet เขาพูดว่า "ด้ายไม่สามารถอ่านตัวแปรระเหยได้โดยไม่ตรวจสอบว่าด้ายอื่น ๆ ได้ทำการเขียน" แต่จะเกิดอะไรขึ้นถ้ามีเธรดหนึ่งอยู่ระหว่างการเขียนและเธรดที่สองกำลังอ่านอยู่ !! ฉันผิดหรือเปล่า? สภาพการแข่งขันในการทำงานของอะตอมไม่ใช่หรือ
hardik

3
@Hardik: โปรดสร้างคำถามอื่นเพื่อรับการตอบสนองเพิ่มเติมเกี่ยวกับสิ่งที่คุณถามนี่เป็นเพียงคุณและฉันและความคิดเห็นไม่เหมาะสำหรับการถามคำถาม อย่าลืมโพสต์ลิงก์ไปยังคำถามใหม่ที่นี่เพื่อให้ฉันสามารถติดตามได้
Tomasz Nurkiewicz

61

การประกาศตัวแปรในรูปแบบระเหยหมายความว่าการแก้ไขค่าจะมีผลทันทีต่อหน่วยความจำจริงของตัวแปร คอมไพเลอร์ไม่สามารถปรับการอ้างอิงใด ๆ ที่ทำกับตัวแปรให้เหมาะสม สิ่งนี้รับประกันว่าเมื่อเธรดหนึ่งแก้ไขตัวแปรเธรดอื่นทั้งหมดจะเห็นค่าใหม่ทันที (ไม่รับประกันสำหรับตัวแปรที่ไม่ลบเลือน)

การประกาศตัวแปรอะตอมรับประกันว่าการดำเนินการกับตัวแปรเกิดขึ้นในแฟชั่นอะตอมกล่าวคือขั้นตอนย่อยทั้งหมดของการดำเนินการเสร็จสมบูรณ์ภายในเธรดที่ถูกดำเนินการและไม่ถูกขัดจังหวะโดยเธรดอื่น ตัวอย่างเช่นการดำเนินการแบบเพิ่มและทดสอบต้องใช้ตัวแปรที่จะเพิ่มขึ้นแล้วเปรียบเทียบกับค่าอื่น; การดำเนินการของอะตอมรับประกันได้ว่าทั้งสองขั้นตอนเหล่านี้จะเสร็จสมบูรณ์ราวกับว่าพวกเขาเป็นการดำเนินการที่แยกไม่ได้ / ไม่ขาดตอน

การซิงโครไนซ์การเข้าถึงทั้งหมดกับตัวแปรอนุญาตให้เธรดเดียวเท่านั้นในแต่ละครั้งเพื่อเข้าถึงตัวแปรและบังคับให้เธรดอื่นทั้งหมดรอการเข้าถึงเธรดนั้นเพื่อปล่อยการเข้าถึงตัวแปร

การเข้าถึงแบบซิงโครไนซ์นั้นคล้ายคลึงกับการเข้าถึงแบบอะตอมมิก แต่การปฏิบัติการแบบปรมาณูจะถูกนำไปใช้ในระดับที่ต่ำกว่าของการเขียนโปรแกรม นอกจากนี้ยังเป็นไปได้ทั้งหมดที่จะซิงโครไนซ์เฉพาะการเข้าถึงตัวแปรและอนุญาตการเข้าถึงอื่นที่ไม่ซิงโครไนซ์ (เช่นซิงโครไนซ์การเขียนทั้งหมดไปยังตัวแปร แต่ไม่มีการอ่านจากมัน)

Atomicity การซิงโครไนซ์และความผันผวนเป็นคุณลักษณะที่เป็นอิสระ แต่โดยทั่วไปจะใช้ร่วมกันเพื่อบังคับใช้ความร่วมมือของเธรดที่เหมาะสมสำหรับการเข้าถึงตัวแปร

ภาคผนวก (เมษายน 2559)

การเข้าถึงตัวแปรให้ตรงกันโดยปกติจะใช้งานโดยใช้มอนิเตอร์หรือเซมาฟอร์ สิ่งเหล่านี้เป็นกลไกmutexระดับต่ำ(การยกเว้นซึ่งกันและกัน) ที่อนุญาตให้เธรดได้รับการควบคุมตัวแปรหรือบล็อกของรหัสโดยเฉพาะบังคับให้เธรดอื่นทั้งหมดรอถ้าพวกเขาพยายามรับ mutex เดียวกันด้วย เมื่อเธรดที่เป็นเจ้าของออก mutex แล้วเธรดอื่นสามารถรับ mutex ได้

ภาคผนวก (กรกฎาคม 2016)

การประสานข้อมูลที่เกิดขึ้นบนวัตถุ ซึ่งหมายความว่าการเรียกใช้วิธีการซิงโครไนซ์ของคลาสจะล็อคthisวัตถุของการโทร วิธีการทำข้อมูลให้ตรงกันแบบคงที่จะล็อคClassวัตถุเอง

ในทำนองเดียวกันการเข้าบล็อกที่ซิงโครไนซ์จะต้องล็อคthisวัตถุของวิธีการ

ซึ่งหมายความว่าวิธีการทำข้อมูลให้ตรงกัน (หรือบล็อก) สามารถดำเนินการในหลายหัวข้อในเวลาเดียวกันถ้าพวกเขาจะล็อคที่แตกต่างกันวัตถุ แต่เพียงหนึ่งหัวข้อสามารถดำเนินการวิธีการทำข้อมูลให้ตรงกัน (หรือบล็อก) ในเวลาใดก็ตามสำหรับเดี่ยววัตถุ


25

ระเหย:

volatileเป็นคำหลัก volatileบังคับให้เธรดทั้งหมดได้รับค่าล่าสุดของตัวแปรจากหน่วยความจำหลักแทนแคช ไม่จำเป็นต้องล็อคเพื่อเข้าถึงตัวแปรระเหย กระทู้ทั้งหมดสามารถเข้าถึงค่าตัวแปรระเหยได้ในเวลาเดียวกัน

การใช้volatileตัวแปรช่วยลดความเสี่ยงของข้อผิดพลาดความสอดคล้องของหน่วยความจำเนื่องจากการเขียนใด ๆ ไปยังตัวแปรระเหยสร้างความสัมพันธ์ที่เกิดขึ้นก่อนกับการอ่านตัวแปรเดียวกันที่ตามมา

ซึ่งหมายความว่าการเปลี่ยนแปลงvolatileตัวแปรสามารถมองเห็นกระทู้อื่น ๆได้เสมอ มีอะไรเพิ่มเติมก็ยังหมายถึงว่าเมื่อด้ายอ่านvolatileตัวแปรที่เห็นไม่ได้เป็นเพียงการเปลี่ยนแปลงล่าสุดที่จะผันผวน แต่ยังมีผลข้างเคียงของรหัสที่นำขึ้นการเปลี่ยนแปลง

เวลาใช้: หนึ่งเธรดจะแก้ไขข้อมูลและเธรดอื่น ๆ จะต้องอ่านค่าข้อมูลล่าสุด หัวข้ออื่น ๆ จะดำเนินการบางอย่าง แต่พวกเขาจะไม่ปรับปรุงข้อมูล

AtomicXXX:

AtomicXXXคลาสสนับสนุนการเขียนโปรแกรมที่ปลอดภัยโดยไม่มีล็อคเกลียวสำหรับตัวแปรเดี่ยว AtomicXXXคลาสเหล่านี้(เหมือนAtomicInteger) แก้ไขข้อผิดพลาดที่ไม่สอดคล้องกันของหน่วยความจำ / ผลข้างเคียงของการแก้ไขตัวแปรระเหยซึ่งเข้าถึงได้ในหลายเธรด

เวลาใช้: หลายกระทู้สามารถอ่านและแก้ไขข้อมูล

ตรงกัน:

synchronizedเป็นคำหลักที่ใช้ในการป้องกันวิธีหรือบล็อกรหัส โดยวิธีการทำข้อมูลให้ตรงกันมีสองผล:

  1. ครั้งแรกเป็นไปไม่ได้ที่การเรียกใช้เมธอดสองครั้งsynchronizedบนวัตถุเดียวกันเพื่อแทรกสอด เมื่อเธรดหนึ่งกำลังเรียกใช้synchronizedเมธอดสำหรับวัตถุเธรดอื่นทั้งหมดที่เรียกใช้synchronizedเมธอดสำหรับบล็อกวัตถุเดียวกัน (ระงับการประมวลผล) จนกระทั่งเธรดแรกเสร็จสิ้นด้วยวัตถุ

  2. ประการที่สองเมื่อsynchronizedเมธอดออกไปมันจะสร้างความสัมพันธ์ที่เกิดขึ้นก่อนโดยอัตโนมัติกับการเรียกใช้synchronizedเมธอดสำหรับวัตถุเดียวกันที่ตามมา สิ่งนี้รับประกันว่าการเปลี่ยนแปลงสถานะของวัตถุสามารถมองเห็นได้กับกระทู้ทั้งหมด

เวลาใช้: หลายกระทู้สามารถอ่านและแก้ไขข้อมูล ตรรกะทางธุรกิจของคุณไม่เพียง แต่ปรับปรุงข้อมูล แต่ยังดำเนินการปรมาณู

AtomicXXXเทียบเท่าvolatile + synchronizedแม้ว่าการใช้งานจะแตกต่างกัน AmtomicXXXขยายvolatileตัวแปร + compareAndSetวิธีการ แต่ไม่ใช้การซิงโครไนซ์

คำถาม SE ที่เกี่ยวข้อง:

ความแตกต่างระหว่างสารระเหยและซิงโครไนซ์ใน Java

บูลีนระเหยกับ AtomicBoolean

บทความดีๆที่ควรอ่าน: (เนื้อหาข้างต้นนำมาจากหน้าเอกสารเหล่านี้)

https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html

https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html


2
นี่เป็นคำตอบแรกที่กล่าวถึงความหมายที่เกิดขึ้นก่อนความหมายของคำหลัก / คุณสมบัติที่อธิบายไว้ซึ่งมีความสำคัญในการทำความเข้าใจว่าสิ่งเหล่านั้นส่งผลกระทบต่อการเรียกใช้โค้ดอย่างไร คำตอบที่โหวตให้สูงกว่าพลาดมุมมองนี้
jhyot

5

ฉันรู้ว่าสองกระทู้ไม่สามารถเข้าสู่ Synchronize block ได้ในเวลาเดียวกัน

สองเธรดไม่สามารถป้อนบล็อกที่ซิงโครไนซ์บนวัตถุเดียวกันสองครั้ง ซึ่งหมายความว่าสองกระทู้สามารถเข้าสู่บล็อกเดียวกันบนวัตถุที่แตกต่างกัน ความสับสนนี้สามารถนำไปสู่รหัสเช่นนี้

private Integer i = 0;

synchronized(i) {
   i++;
}

สิ่งนี้จะไม่ทำงานตามที่คาดไว้เพราะอาจล็อควัตถุที่แตกต่างกันในแต่ละครั้ง

ถ้านี่เป็นจริงกว่าวิธีนี้ atomic.incrementAndGet () ทำงานโดยไม่ซิงโครไนซ์ ?? และด้ายปลอดภัยหรือไม่?

ใช่. ไม่ใช้การล็อกเพื่อให้เกิดความปลอดภัยของเธรด

หากคุณต้องการทราบวิธีการทำงานโดยละเอียดยิ่งขึ้นคุณสามารถอ่านรหัสสำหรับพวกเขาได้

และอะไรคือความแตกต่างระหว่างการอ่านและการเขียนภายในกับ Volatile Variable / Atomic Variable

ระดับอะตอมใช้ฟิลด์ระเหย ไม่มีความแตกต่างในฟิลด์ ความแตกต่างคือการดำเนินการ คลาส Atomic ใช้การเปรียบเทียบ CompareAndSwap หรือ CAS

ฉันอ่านในบางบทความที่เธรดมีสำเนาโลคัลของตัวแปรนั่นคืออะไร ??

ฉันสามารถสันนิษฐานได้ว่ามันหมายถึงความจริงที่ว่าแต่ละซีพียูมีมุมมองแคชของหน่วยความจำซึ่งแตกต่างจากซีพียูอื่น ๆ เพื่อให้แน่ใจว่า CPU ของคุณมีมุมมองข้อมูลที่สอดคล้องกันคุณต้องใช้เทคนิคความปลอดภัยของเธรด

นี่เป็นปัญหาเมื่อมีการแชร์หน่วยความจำอย่างน้อยหนึ่งเธรดที่อัพเดต


@ Niket Thakur คุณแน่ใจหรือไม่ จำนวนเต็มไม่เปลี่ยนรูป ดังนั้น i ++ อาจจะทำการ unbox โดยอัตโนมัติเพิ่มค่าจากนั้นสร้างจำนวนเต็มใหม่ซึ่งไม่เหมือนกับอินสแตนซ์ก่อนหน้านี้ ลองทำให้ i สุดท้ายและคุณจะได้รับข้อผิดพลาดของคอมไพเลอร์เมื่อโทร i ++
fuemf5

2

ทำข้อมูลให้ตรงกัน Vs Atomic Vs Volatile:

  • Volatile และ Atomic นั้นจะใช้กับตัวแปรเท่านั้นในขณะที่ใช้วิธีการ Synchronized
  • ความมั่นใจในการมองเห็นไม่ใช่อะตอมมิก / ความมั่นคงของวัตถุในขณะที่ทั้งคู่มั่นใจในการมองเห็นและอะตอมมิก
  • การจัดเก็บตัวแปรแบบระเหยใน RAM และเข้าถึงได้เร็วขึ้น แต่เราไม่สามารถบรรลุถึงความปลอดภัยของเธรดหรือการซิงโครไนซ์รายการที่มีการซิงโครไนซ์
  • ทำให้ข้อมูลตรงกันเป็นบล็อกหรือวิธีการทำข้อมูลให้ตรงกันในขณะที่ทั้งสองไม่ได้ เราสามารถเธรดหลายบรรทัดได้อย่างปลอดภัยด้วยความช่วยเหลือของคำสำคัญที่ซิงโครไนซ์ในขณะที่ทั้งคู่ไม่สามารถทำสิ่งเดียวกัน
  • การซิงโครไนซ์สามารถล็อควัตถุคลาสเดียวกันหรือวัตถุคลาสอื่นในขณะที่ทั้งสองไม่สามารถทำได้

โปรดแก้ไขฉันหากมีสิ่งใดที่ฉันพลาด


1

การทำข้อมูลให้ตรงกันแบบระเหย + เป็นวิธีแก้ปัญหาที่เข้าใจง่ายสำหรับการดำเนินการ (คำสั่ง) เพื่อให้เป็นอะตอมมิกอย่างสมบูรณ์ซึ่งรวมถึงคำแนะนำหลายอย่างสำหรับซีพียู

พูดเช่น: ระเหย int i = 2; i ++ ซึ่งไม่มีอะไรนอกจาก i = i + 1; ซึ่งทำให้ฉันเป็นค่า 3 ในหน่วยความจำหลังจากการดำเนินการของคำสั่งนี้ ซึ่งรวมถึงการอ่านค่าที่มีอยู่จากหน่วยความจำสำหรับ i (ซึ่งก็คือ 2) โหลดลงใน CPU register และลงทะเบียนด้วยการคำนวณโดยการเพิ่มค่าที่มีอยู่ด้วยหนึ่ง (2 + 1 = 3 ในการสะสม) จากนั้นเขียนกลับมา กลับไปที่หน่วยความจำ การดำเนินการเหล่านี้ไม่เพียงพอสำหรับอะตอมแม้ว่าค่าของ i จะเปลี่ยนแปลงได้ ฉันเป็นสิ่งที่ระเหยง่ายรับประกันว่าการอ่าน / เขียนจากหน่วยความจำเดียวนั้นเป็นแบบอะตอมมิกและไม่ใช่แบบหลายจุด ดังนั้นเราจำเป็นต้องซิงโครไนซ์รอบ i ++ เพื่อให้มันเป็นคำสั่งปรมาณูที่ใช้พิสูจน์ได้ จำข้อเท็จจริงที่ว่างบรวมหลายงบ

หวังว่าคำอธิบายจะชัดเจนเพียงพอ


1

Java volifier modifier เป็นตัวอย่างของกลไกพิเศษเพื่อรับประกันว่าการสื่อสารเกิดขึ้นระหว่างเธรด เมื่อเธรดหนึ่งเขียนไปยังตัวแปรที่ระเหยได้และอีกเธรดหนึ่งเห็นว่าการเขียนเธรดแรกจะบอกที่สองเกี่ยวกับเนื้อหาทั้งหมดของหน่วยความจำจนดำเนินการเขียนไปยังตัวแปรระเหย

การทำงานแบบปรมาณูดำเนินการในหน่วยงานเดียวโดยไม่มีการแทรกแซงจากการปฏิบัติการอื่น การดำเนินการปรมาณูเป็นสิ่งจำเป็นในสภาพแวดล้อมแบบมัลติเธรดเพื่อหลีกเลี่ยงความไม่สอดคล้องกันของข้อมูล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.