bool compare_exchange_weak (T& expected, T val, ..);
compare_exchange_weak()
เป็นหนึ่งในการเปรียบเทียบแบบดั้งเดิมของการแลกเปลี่ยนที่มีให้ใน C ++ 11 มันอ่อนแอexpected
ในแง่ที่ว่ามันกลับเท็จแม้ว่ามูลค่าของวัตถุที่มีค่าเท่ากับ นี่เป็นเพราะความล้มเหลวปลอมในบางแพลตฟอร์มที่มีการใช้ลำดับของคำสั่ง (แทนที่จะเป็นหนึ่งใน x86) เพื่อใช้งาน บนแพลตฟอร์มดังกล่าวการสลับบริบทการโหลดที่อยู่เดียวกัน (หรือบรรทัดแคช) ซ้ำโดยเธรดอื่น ฯลฯ อาจทำให้ระบบดั้งเดิมล้มเหลว มันspurious
ไม่ใช่ค่าของวัตถุ (ไม่เท่ากับexpected
) ที่ทำให้การดำเนินการล้มเหลว แต่มันเป็นปัญหาเรื่องเวลา
แต่สิ่งที่ทำให้ฉันไขปริศนาคือสิ่งที่พูดใน C ++ 11 Standard (ISO / IEC 14882)
29.6.5 .. ผลที่ตามมาของความล้มเหลวปลอมคือการใช้การเปรียบเทียบและแลกเปลี่ยนที่อ่อนแอเกือบทั้งหมดจะวนเวียน
เหตุใดจึงต้องวนซ้ำในการใช้งานเกือบทั้งหมด ? นั่นหมายความว่าเราจะวนซ้ำเมื่อมันล้มเหลวเพราะความล้มเหลวปลอม ๆ ? ถ้าเป็นเช่นนั้นทำไมเราต้องใช้compare_exchange_weak()
และเขียนลูปด้วยตัวเอง? เราสามารถใช้compare_exchange_strong()
สิ่งที่ฉันคิดว่าควรกำจัดความล้มเหลวปลอมให้เราได้ อะไรคือกรณีการใช้งานทั่วไปของcompare_exchange_weak()
?
คำถามอื่นที่เกี่ยวข้อง ในหนังสือของเขา "C ++ Concurrency In Action" Anthony กล่าวว่า
//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:
bool expected=false;
extern atomic<bool> b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);
//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.
ทำไมจึงอยู่!expected
ในเงื่อนไขการวนซ้ำ? มีไว้เพื่อป้องกันไม่ให้เธรดทั้งหมดอดอาหารและไม่มีความคืบหน้าในบางครั้งหรือไม่?
แก้ไข: (คำถามสุดท้าย)
บนแพลตฟอร์มที่ไม่มีคำสั่ง CAS ฮาร์ดแวร์ทั้งเวอร์ชันที่อ่อนแอและแข็งแกร่งจะถูกนำไปใช้โดยใช้ LL / SC (เช่น ARM, PowerPC เป็นต้น) ดังนั้นจึงมีความแตกต่างระหว่างสองลูปต่อไปนี้หรือไม่? ทำไมถ้ามี? (สำหรับฉันแล้วพวกเขาควรมีประสิทธิภาพใกล้เคียงกัน)
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..))
{ .. }
ฉันมาพร้อมกับคำถามสุดท้ายที่พวกคุณพูดถึงว่าอาจมีความแตกต่างด้านประสิทธิภาพในลูป นอกจากนี้ยังกล่าวถึงโดยมาตรฐาน C ++ 11 (ISO / IEC 14882):
เมื่อการเปรียบเทียบและแลกเปลี่ยนอยู่ในวงรอบเวอร์ชันที่อ่อนแอจะให้ประสิทธิภาพที่ดีกว่าในบางแพลตฟอร์ม
แต่ตามที่วิเคราะห์ไว้ข้างต้นสองเวอร์ชันในลูปควรให้ประสิทธิภาพที่เหมือนกัน / ใกล้เคียงกัน อะไรคือสิ่งที่ฉันคิดถึง?