1012 Chapter 18: Concurrency18.7 AtomicsIn the first example for condi การแปล - 1012 Chapter 18: Concurrency18.7 AtomicsIn the first example for condi ไทย วิธีการพูด

1012 Chapter 18: Concurrency18.7 At

1012 Chapter 18: Concurrency
18.7 Atomics
In the first example for condition variables (see Section 18.6.1, page 1003), we used a Boolean
value readyFlag to let one thread signal that something is prepared or provided for another thread.
Now, you might wonder why we still need a mutex here. If we have a Boolean value, why can’t
we concurrently let one thread change the value while another thread checks it? The moment the
providing thread sets the Boolean to true, the observing thread should be able to see that and
perform the consequential processing.
As introduced in Section 18.4, page 982, we have two problems here:
1. In general, reading and writing even for fundamental data types is not atomic. Thus, you might
read a half-written Boolean, which according to the standard results in undefined behavior.
2. The generated code might change the order of operations, so the providing thread might set the
ready flag before the data is provided, and the consuming thread might process the data before
evaluating the ready flag.
With a mutex, both problems are solved, but a mutex might be a relatively expensive operation in
both necessary resources and latency of the exclusive access. So, instead of using mutexes and lock,
it might be worth using atomics instead.
In this section, I first introduce the high-level interface of atomics, which provides atomic operations
using the default guarantee regarding the order of memory access. This default guarantee
provides sequential consistency, which means that in a thread, atomic operations are guaranteed to
happen in the order as programmed. Thus, problems of reordered statements as introduced in Section
18.4.3, page 986, do not apply. At the end of this section, I present the low-level interface of
atomics: operations with relaxed order guarantees.
Note that the C++ standard library does not distinguish between a high-level and a low-level
atomics interface. The term low-level was introduced by Hans Boehm, one of the authors of the library.
Sometimes, it is also called the weak, or relaxed, atomic interface, and the high-level interface
is sometimes also known as the normal, or strong, atomic interface.
18.7.1 Example of Using Atomics
Let’s transfer the example from Section 18.6.1, page 1003, into a program using atomics:
#include // for atomic types
...
std::atomic readyFlag(false);
void thread1()
{
// do something thread2 needs as preparation
...
readyFlag.store(true);
}
www.it-ebooks.info
18.7 Atomics 1013
void thread2()
{
// wait until readyFlag is true (thread1 is done)
while (!readyFlag.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// do whatever shall happen after thread1 has prepared things
...
}
First, we include the header file , where atomics are declared:
#include
Then, we declare an atomic object, using the std::atomic class template:
std::atomic readyFlag(false);
In principle, you can use any trivial, integral, or pointer type as template parameter.
Note that you always should initialize atomic objects because the default constructor does not
fully initialize it (it’s not that the initial value is undefined, it is that the lock is uninitialized).26
For static-duration atomic objects, you should use a constant to initialize them. If only the default
constructor is used, the only operation allowed next is to call a global atomic_init() operation as
follows:
std::atomic readyFlag;
...
std::atomic_init(&readyFlag,false);
This way of initialization is provided to be able to write code that also compiles in C (see Section
18.7.3, page 1019).
The two most important statements to deal with atomics are store() and load():
• store() assigns a new value.
• load() yields the current value.
The important point is that these operations are guaranteed to be atomic, so we don’t need a mutex
to set the ready flag, as we had to without atomics. Thus, in the first thread, instead of
{
std::lock_guard lg(readyMutex);
readyFlag = true;
} // release lock
we simply can program:
readyFlag.store(true);
26 Thanks to Lawrence Crowl for pointing this out.
www.it-ebooks.info
1014 Chapter 18: Concurrency
In the second thread, instead of
{
std::unique_lock l(readyFlagMutex);
while (!readyFlag) {
l.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
l.lock();
}
} // release lock
we have to implement only the following:
while (!readyFlag.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
However, when using condition variables, we still need the mutex for consuming the condition
variable:
// wait until thread1 is ready (readyFlag is true)
{
std::unique_lock l(readyMutex);
readyCondVar.wait(l, []{ return readyFlag.load(); });
} // release lock
For atomic types, you can still use the “useful,” “ordinary” operations, such as assignments, automatic
conversions to integral types, increments, decrements, and so on:
std::atomic ab(false);
ab = true;
if (ab) {
...
}
std::atomic ai(0);
int x = ai;
ai = 10;
ai++;
ai-=17;
Note, however, that to provide atomicity, some usual behavior might be slightly different. For example,
the assignment operator yields the assigned value instead of a reference to the atomic the value
was assigned to. See Section 18.7.2, page 1016, for details.
Let’s look at a complete example using atomics:
// concurrency/atomics1.cpp
#include // for atomics
#include // for async() and futures
www.it-ebooks.info
18.7 Atomics 1015
#include // for this_thread
#include // for durations
#include
long data;
std::atomic readyFlag(false);
void provider ()
{
// after reading a character
std::cout
0/5000
จาก: -
เป็น: -
ผลลัพธ์ (ไทย) 1: [สำเนา]
คัดลอก!
1012 บท 18: เกิด
นี้ Atomics
แรกสำหรับตัวแปรเงื่อนไข (ดูส่วน 18.6.1 หน้า 1003), เราใช้บูลีนการ
readyFlag ค่าให้เธรดหนึ่งสัญญาณว่า บางสิ่งบางอย่างจะเตรียม หรือสำหรับเธรดอื่นได้
ตอนนี้ คุณอาจสงสัยว่า ทำไมเรายังต้องมี mutex ที่นี่ ถ้าเรามีค่าบูลีน ทำไมไม่
เราพร้อมให้เปลี่ยนค่าในขณะที่เธรดอื่นตรวจสอบเธรดหนึ่ง ขณะ
ให้หัวข้อตั้งค่าบูลีนจริง หัวข้อสังเกตจะเห็นว่า และ
ดำเนินการต่อการประมวลผล
แนะนำในส่วน 18.4 หน้า 982 เรามีสองปัญหาที่นี่:
1 ทั่วไป อ่าน และเขียนสำหรับชนิดข้อมูลพื้นฐานได้อะตอม ดังนั้น คุณอาจ
อ่านการเขียนครึ่งบูลีน ซึ่งตามมาตรฐานผลลัพธ์ในลักษณะการทำงานไม่
2 รหัสที่สร้างขึ้นอาจเปลี่ยนแปลงลำดับของการดำเนินการ เพื่อตั้งหัวข้อให้การ
พร้อมธงก่อนให้ข้อมูล และด้ายนานอาจประมวลผลข้อมูลก่อน
ประเมินพร้อมธงงาน
มี mutex ปัญหาทั้งสองมีแก้ไข แต่มี mutex อาจดำเนินการค่อนข้างแพงใน
ทรัพยากรที่จำเป็นและเวลาแฝงของการเข้าถึงแบบเอกสิทธิ์เฉพาะบุคคล ดังนั้น แทนการใช้ mutexes และล็อค,
มันอาจจะมีมูลค่าใช้แทน atomics.
ในส่วนนี้ ฉันก่อนนำอินเตอร์เฟซระดับสูงของ atomics ซึ่งมีการดำเนินการที่อะตอม
ใช้หนังสือค้ำประกันเริ่มต้นเกี่ยวกับลำดับของการเข้าถึงหน่วยความจำได้ หนังสือค้ำประกันนี้เริ่มต้น
ให้สอดคล้องต่อเนื่องกัน ซึ่งหมายความ ว่า ในเธรด การดำเนินการที่อะตอมจะรับประกัน
เกิดขึ้นในใบสั่งเป็นโปรแกรม ดังนั้น ปัญหาของประมวลคำที่นำมาใช้ในส่วน
18.4.3 หน้า 986 ไม่สามารถใช้ ที่ตอนท้ายของส่วนนี้ ฉันปัจจุบันอินเทอร์เฟซที่ระดับต่ำของ
atomics: การดำเนินงานพร้อมรับประกันคุณภาพสั่งผ่อนคลาย
หมายเหตุที่ไลบรารีมาตรฐาน C ไม่แยกความแตกต่างระหว่างความสูงและระดับต่ำ
atomics อินเตอร์เฟซ ระยะต่ำถูกนำ โดยฮานส์ Boehm ผู้เขียนของไลบรารีหนึ่ง
บางครั้ง มันยังเรียกว่าอ่อนแอ การผ่อน คลาย อินเตอร์เฟซอะตอม และอินเทอร์เฟซพื้นฐาน
เป็นบางครั้งรู้จักกัน เป็นปกติ หรือแข็ง แกร่ง อะตอมอินเตอร์เฟซ
18.7.1 ตัวอย่างของการใช้ Atomics
ลองโอนย้ายตัวอย่างจากส่วน 18.6.1 หน้า 1003 ลงโปรแกรมใช้ atomics:
#include / / สำหรับชนิดอะตอม
...
มาตรฐาน:: readyFlag อะตอม (เท็จ);
โมฆะ thread1()
{
/ / ทำอะไร thread2 ต้องเป็น preparation
...
readyFlag.store(true);
}
www.it-ebooks.info
18.7 Atomics 1013
โมฆะ thread2()
{
/ / รอ readyFlag เป็นจริง (thread1 เสร็จสิ้น)
ขณะ (! readyFlag.load()) {
มาตรฐาน::this_thread::sleep_for(std::chrono::milliseconds(100));
}
/ / ทำสิ่งที่จะเกิดขึ้นหลังจาก thread1 ได้เตรียมสิ่ง
...
}
ครั้งแรก เรารวมหัวข้อแฟ้ม ที่ประกาศ atomics:
#include
แล้ว เราประกาศวัตถุอะตอม ใช้เท็มเพลตชั้น<>std::atomic:
มาตรฐาน:: readyFlag อะตอม (เท็จ);
หลัก คุณสามารถใช้ทฤษฎีบูรณาการใด ๆ เล็กน้อย หรือชนิดชี้เป็นพารามิเตอร์แบบนั้น
หมายเหตุว่า คุณเสมอควรเตรียมใช้งานวัตถุอะตอม เพราะตัวเริ่มสร้างไม่
เต็มเตรียมใช้งาน (ไม่ได้อยู่ที่ค่าเริ่มต้นคือไม่ ว่าล็อคไม่เป็น) 26
คงระยะเวลาวัตถุอะตอม คุณควรใช้ค่าคงที่เพื่อเริ่มต้นพวกเขา ถ้าเริ่มต้น
ใช้ตัวสร้าง การดำเนินการเท่านั้นได้ต่อไปจะเรียก atomic_init() ส่วนกลางดำเนินการเป็น
ดังต่อไปนี้:
มาตรฐาน:: อะตอม readyFlag;
...
std::atomic_init(&readyFlag,false);
เริ่มต้นวิธีนี้ไว้เพื่อให้สามารถเขียนรหัสที่ยังคอมไพล์ใน C (ดูส่วน
18.7.3 หน้า 1019) .
งบสำคัญสองจัดการกับ atomics มี store() และโหลด():
• store() กำหนดค่าใหม่
• load() ทำให้ในปัจจุบันมูลค่าการ
จุดสำคัญอยู่ที่การดำเนินการเหล่านี้จะรับประกันได้อะตอม ดังนั้นเราไม่จำเป็นมี mutex
ตั้งธงพร้อม มี โดย atomics ดังนั้น ในหัวข้อแรก แทน
{
std::lock_guard lg (readyMutex);
readyFlag = true;
} / / ปลดล็อก
เราก็สามารถ program:
readyFlag.store(true);
26 ด้วยลอว์เรนซ์ Crowl สำหรับชี้ออกนี้
www.it-ebooks.info
บท 1014 18: เกิด
ในหัวข้อที่สอง แทน
{
std::unique_lock l (readyFlagMutex);
ขณะ (! readyFlag) {
l.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
l.lock();
}
} / / ปลดล็อก
เราต้องใช้เฉพาะต่อไปนี้:
ขณะ (! readyFlag.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
อย่างไรก็ตาม เมื่อใช้ตัวแปรเงื่อนไข เรายังคงต้อง mutex ที่สำหรับใช้เงื่อนไข
แปร:
/ / รอ thread1 เสร็จ (readyFlag เป็นจริง)
{
std::unique_lock l (readyMutex)
readyCondVar.wait (l {คืน readyFlag.load(); } []);
} / / ปลดล็อก
ชนิดอะตอม คุณยังสามารถใช้งาน "ปกติ" "ประโยชน์ เช่นกำหนด อัตโนมัติ
แปลงไปเป็นชนิด ที decrements และอื่น ๆ:
มาตรฐาน:: อะตอม ab (เท็จ);
ab =จริง;
ถ้า (ab) {
...
}
std::atomic อาย (0);
int x =ไอ;
ไอ = 10;
ไอ;
ไอ-= 17;
ทราบ อย่างไรก็ตาม ว่า ให้ atomicity พฤติกรรมตามปกติบางอย่างอาจต่างกันเล็กน้อย ตัวอย่าง,
ทำให้ตัวดำเนินการกำหนดค่ากำหนดแทนการอ้างอิงไปที่อะตอมค่า
ถูกกำหนดให้ ดูส่วน 18.7.2 หน้า 1016 สำหรับรายละเอียด
ของให้ดูเป็นตัวอย่างที่สมบูรณ์ที่ใช้ atomics:
/ / concurrency/atomics1.cpp
#include / / สำหรับ atomics
#include / / async() และในอนาคต
www.it-ebooks.info
18.7 Atomics 1015
#include / / this_thread
#include / / สำหรับช่วงเวลา
#include
ข้อมูลยาว;
มาตรฐาน:: readyFlag อะตอม (เท็จ);
โมฆะ()ผู้ให้บริการ
{
/ / หลัง จากอ่านอักขระ
std::cout << "" << std::endl;
std::cin.get();
/ / ให้ข้อมูลบาง
ข้อมูล = 42;
/ / และสัญญาณ readiness
readyFlag.store (ทรู);
}
โมฆะ(ผู้บริโภค)
{
/ / รอความพร้อม และทำอย่างอื่น
ขณะ (! readyFlag.load()) {
std::cout.put('.')flush();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
/ / และกระบวนการที่ให้ข้อมูล
std::cout << "
value: " << ข้อมูล << std::endl;
}
int main()
{
/ / ผู้ให้บริการและผู้บริโภคเริ่มต้น
อัตโนมัติ p = std::async (std::launch::async ผู้ให้บริการ);
c อัตโนมัติ = std::async (std::launch::async ผู้บริโภค);
}
กระทู้ที่นี่ provider() แรก ให้ข้อมูลบางอย่างแล้ว ใช้ store() เป็นสัญญาณที่ข้อมูล
ไว้:
ข้อมูล = 42 / / ให้บาง data
readyFlag.store(true) / / และสัญญาณพร้อม
www.it-ebooks.info
การแปล กรุณารอสักครู่..
ผลลัพธ์ (ไทย) 2:[สำเนา]
คัดลอก!
1012 บทที่ 18: Concurrency
18.7 อะตอม
ในตัวอย่างแรกสำหรับตัวแปรสภาพ (ดูมาตรา 18.6.1, หน้า 1003) เราใช้บูลีน
readyFlag ค่าที่จะปล่อยให้สัญญาณด้ายหนึ่งว่าสิ่งที่จะทำหรือให้หัวข้ออื่น
ตอนนี้คุณอาจจะ สงสัยว่าทำไมเรายังคงต้อง mutex ที่นี่ ถ้าเรามีค่าบูลีนทำไมไม่สามารถ
ที่เราพร้อมให้หนึ่งด้ายเปลี่ยนค่าในขณะที่หัวข้ออื่นตรวจสอบได้หรือไม่ ขณะนี้
ให้ด้ายชุดบูลีนเป็นจริงหัวข้อการสังเกตควรจะสามารถที่จะเห็นว่าและ
ดำเนินการประมวลผลที่ตามมา
เป็นที่รู้จักในมาตรา 18.4, หน้า 982 เรามีสองปัญหาที่นี่:
1 โดยทั่วไปการอ่านและการเขียนได้สำหรับชนิดข้อมูลพื้นฐานที่ไม่ได้เป็นอะตอม ดังนั้นคุณอาจจะ
อ่านเขียนครึ่งบูลีนซึ่งเป็นไปตามผลการมาตรฐานในการทำงานที่ไม่ได้กำหนด
2 รหัสที่สร้างขึ้นอาจจะเปลี่ยนลำดับของการดำเนินงานเพื่อให้ด้ายอาจตั้ง
ธงพร้อมก่อนที่ข้อมูลจะถูกให้และด้ายบริโภคอาจประมวลผลข้อมูลก่อนที่จะ
ประเมินธงพร้อม
ด้วย mutex ปัญหาทั้งสองจะแก้ไข แต่ mutex อาจจะมีการดำเนินงานที่ค่อนข้างมีราคาแพงใน
ทั้งทรัพยากรที่จำเป็นและแฝงของสิทธิพิเศษ ดังนั้นแทนที่จะใช้ mutexes และล็อค
มันอาจจะมีมูลค่าการใช้อะตอมแทน
ในส่วนนี้ครั้งแรกที่ผมแนะนำอินเตอร์เฟซระดับสูงของอะตอมซึ่งมีการดำเนินงานของอะตอม
โดยใช้การรับประกันเริ่มต้นที่เกี่ยวกับคำสั่งของการเข้าถึงหน่วยความจำ รับประกันเริ่มต้นนี้
ให้สอดคล้องต่อเนื่องซึ่งหมายความว่าในหัวข้อการดำเนินงานของอะตอมจะรับประกัน
เกิดขึ้นเพื่อเป็นโปรแกรม ดังนั้นปัญหาของงบตับแลบเป็นที่รู้จักในมาตรา
18.4.3, หน้า 986, ไม่สามารถใช้ ในตอนท้ายของส่วนนี้ผมนำเสนออินเตอร์เฟซที่ระดับต่ำของ
อะตอม: การดำเนินงานที่มีการค้ำประกันเพื่อผ่อนคลาย
ทราบว่าห้องสมุด C + + มาตรฐานไม่ได้เห็นความแตกต่างระหว่างระดับสูงและระดับต่ำ
ติดต่ออะตอม ระยะในระดับต่ำได้รับการแนะนำโดยฮันส์ Boehm, หนึ่งในนักเขียนของห้องสมุด
บางครั้งก็เรียกว่าอ่อนแอหรือผ่อนคลายอินเตอร์เฟซอะตอมและอินเตอร์เฟซที่ระดับสูง
เป็นบางครั้งเรียกว่าเป็นปกติหรือที่แข็งแกร่ง อินเตอร์เฟซอะตอม
18.7.1 ตัวอย่างของการใช้อะตอม
ขอโอนตัวอย่างจากมาตรา 18.6.1, หน้า 1003 ลงในโปรแกรมโดยใช้อะตอม:
# include/ / สำหรับชนิดอะตอม
...
std :: อะตอมreadyFlag (เท็จ);
thread1 เป็นโมฆะ ()
{
/ / ทำสิ่งที่ thread2 ต้องเตรียม
...
readyFlag.store (จริง);
}
www.it-ebooks.info
18.7 อะตอม 1013
thread2 เป็นโมฆะ ()
{
/ / รอจนกว่า readyFlag เป็น จริง (thread1 จะทำ)
ขณะที่ {(readyFlag.load ())
std :: this_thread :: sleep_for (std :: โครโนกราฟ :: มิลลิวินาที (100));
}
/ / ทำสิ่งที่จะเกิดขึ้นหลังจาก thread1 ได้จัดเตรียมสิ่งที่
.. .
}
ครั้งแรกที่เรารวมไฟล์ส่วนหัวที่อะตอมมีการประกาศ:
# include
จากนั้นเราจะประกาศเป็นวัตถุอะตอมโดยใช้มาตรฐาน :: อะตอม <> ชั้นแม่แบบ:
std :: อะตอมreadyFlag (เท็จ);
ในหลักการคุณสามารถใช้เล็กน้อยหนึ่งหรือชนิดตัวชี้ใด ๆ ที่เป็นแม่แบบพารามิเตอร์
ทราบว่าคุณควรเริ่มต้นวัตถุอะตอมเพราะสร้างการเริ่มต้นไม่ได้
อย่างเต็มที่เริ่มต้นมัน (มันไม่ได้ว่าเป็นค่าเริ่มต้นไม่ได้กำหนด มันเป็นที่ล็อค uninitialized) 0.26
สำหรับวัตถุอะตอมคงที่ระยะเวลาที่คุณควรใช้อย่างต่อเนื่องในการเริ่มต้นพวกเขา ถ้าเพียง แต่เริ่มต้น
สร้างจะใช้ในการดำเนินการได้รับอนุญาตเท่านั้นต่อไปคือการเรียก atomic_init ทั่วโลก () การดำเนินงานเป็น
ดังนี้
std :: อะตอมreadyFlag;
...
std :: atomic_init (และ readyFlag เท็จ);
วิธีการเริ่มต้นนี้มีไว้เพื่อให้สามารถเขียนโค้ดที่ยังรวบรวมใน C (ดูมาตรา
18.7.3, หน้า 1019)
สองคำที่สำคัญที่สุดในการจัดการ ด้วยอะตอมเป็นร้านค้า () และโหลด ():
•ร้านค้า () กำหนดค่าใหม่
•โหลด () ผลตอบแทนถัวเฉลี่ยค่าปัจจุบัน
จุดสำคัญคือว่าการดำเนินการเหล่านี้ได้รับการรับรองให้เป็นอะตอมดังนั้นเราจึงไม่จำเป็นต้อง mutex
การตั้งธงพร้อมที่เรามีโดยไม่ต้องอะตอม ดังนั้นในหัวข้อแรกแทน
{
std :: lock_guardแอลจี (readyMutex);
readyFlag = true;
} / / ปลดล็อค
เราก็สามารถโปรแกรม:
readyFlag.store (จริง);
26 ขอบคุณ Crowl อเรนซ์เพื่อชี้นี้
www.it-ebooks.info
1014 บทที่ 18: Concurrency
ใน หัวข้อที่สองแทน
{
std :: unique_lockลิตร (readyFlagMutex);
ในขณะที่ (readyFlag!) {
l.unlock ();
std :: this_thread :: sleep_for (std :: โครโนกราฟ :: มิลลิวินาที (100));
l.lock ();
}
} / / ปลดล็อค
เรา มีการดำเนินการเฉพาะดังต่อไปนี้
(! readyFlag.load ()) ในขณะที่ {
std :: this_thread :: sleep_for (std :: โครโนกราฟ :: มิลลิวินาที (100));
}
แต่เมื่อใช้ตัวแปรสภาพเรายังคงต้อง mutex เพื่อใช้เงื่อนไข
ตัวแปร:
/ / รอจนกว่า thread1 พร้อม (readyFlag เป็นความจริง)
{
std :: unique_lockลิตร (readyMutex);
readyCondVar.wait (l, [] {กลับ readyFlag.load ();});
} / / ปลดล็อค
สำหรับประเภทอะตอม, คุณยังสามารถใช้ "ประโยชน์" "ธรรมดาการดำเนินงาน" เช่นการมอบหมายงาน อัตโนมัติ
แปลงชนิดหนึ่ง, เพิ่ม, ลดการและอื่น ๆ :
std :: อะตอมข (เท็จ);
ข = true;
ถ้า (ข) {
...
}
std :: อะตอมเอไอ (0);
int x = ไอ;
ไอ = 10;
ไอ + +
ไอ-= 17;
หมายเหตุ แต่ที่จะให้ atomicity พฤติกรรมปกติบางคนอาจจะแตกต่างกันเล็กน้อย ตัวอย่างเช่น
ผู้ประกอบการที่ได้รับมอบหมายทำให้ค่าที่กำหนดแทนการอ้างอิงถึงอะตอมค่า
ได้รับมอบหมายให้ ดูมาตรา 18.7.2, หน้า 1016 สำหรับรายละเอียด
ลองดูที่เป็นตัวอย่างที่สมบูรณ์โดยใช้อะตอม:
/ / concurrency/atomics1.cpp
# include/ / การอะตอม
# include/ / การ async () และฟิวเจอร์ส
www.it-ebooks.info
18.7 อะตอม 1015
# include/ / การ this_thread
# include/ / สำหรับระยะเวลา
# include
ข้อมูลยาว
std :: อะตอมreadyFlag (เท็จ);
ให้เป็นโมฆะ ()
{
/ / หลังจากที่ได้อ่านตัวอักษร
STD :: ศาล << ""<< std :: endl;
std :: cin.get ();
/ / ให้ข้อมูลบาง
ข้อมูล = 42;
/ / และความพร้อมสัญญาณ
readyFlag.store (จริง);
}
ผู้บริโภคเป็นโมฆะ ()
{
/ / รอความพร้อมและ ทำอย่างอื่น
ในขณะที่ {(readyFlag.load ())
std :: cout.put ('.') ล้าง ().
std :: this_thread :: sleep_for (std :: โครโนกราฟ :: มิลลิวินาที (500));
}
/ / และขั้นตอนการให้ข้อมูล
STD :: ศาล << " nValue:" << ข้อมูล << std :: endl;
}
int หลัก ()
{
/ / เริ่มต้นการให้บริการและผู้บริโภค
รถยนต์ p = std :: async (std :: เปิด :: async ผู้ให้บริการ);
รถยนต์ c = std :: async (std :: เปิดตัว :: async ผู้บริโภค);
}
ที่นี่ให้บริการด้าย () ก่อนให้ข้อมูลบางส่วนแล้วใช้ร้านค้า () เพื่อส่งสัญญาณว่าข้อมูลที่
มีให้:
ข้อมูล = 42 / / ให้บางข้อมูล
readyFlag.store (จริง) / / และสัญญาณความพร้อม
www.it-ebooks.info
การแปล กรุณารอสักครู่..
ผลลัพธ์ (ไทย) 3:[สำเนา]
คัดลอก!
1 บทที่ 18 : การลดลง

อะตอมในตัวอย่างแรกสำหรับตัวแปรสภาวะ ( ดูมาตรา 18.6.1 หน้า 1002 ) เราใช้ค่าบูลีน
readyflag ให้หัวข้อหนึ่ง สัญญาณบางอย่างที่เตรียมไว้ หรือให้หัวข้ออื่น .
ตอนนี้คุณอาจสงสัยว่าทำไมเรายังต้อง mutex ที่นี่เลย ถ้าเรามีค่าบูลีน ทำไมไม่ได้
เราจำเป็นต้องให้หัวข้อเปลี่ยนค่าขณะที่หัวข้ออื่นตรวจสอบได้ ? ขณะที่
ให้ชุดด้ายบูลีนเป็นจริง ด้ายสังเกตจะเห็นว่าแสดงการประมวลผลและ

เป็นสำคัญ แนะนำในส่วนค่าบริการหน้า 982 , เรามีสองปัญหาที่นี่ :
1 ในทั่วไป , การอ่านและการเขียนสำหรับชนิดข้อมูลพื้นฐานไม่ใช่อะตอม ดังนั้น คุณอาจ
อ่านครึ่งเดียวตรรกะ ซึ่งตามผลมาตรฐานพฤติกรรม undefined .
2 รหัสที่สร้างขึ้นจะเปลี่ยนแปลงคำสั่งของการดำเนินงาน เพื่อให้กระทู้อาจจะตั้ง
ธงพร้อมก่อนเป็นข้อมูลให้ และใช้ด้ายอาจกระบวนการประเมินข้อมูลก่อน

mutex ธงพร้อม กับ ทั้ง ปัญหาจะคลี่คลายแต่ mutex อาจจะเป็นงานค่อนข้างแพงใน
ทั้งทรัพยากรที่จำเป็นและศักยภาพของการเข้าถึงแบบเอกสิทธิ์เฉพาะบุคคล ดังนั้น แทนที่จะใช้ mutexes และล็อค ,
มันอาจจะมีมูลค่าการใช้อะตอมแทน .
ในส่วนนี้ ผมแนะนำอินเตอร์เฟซระดับสูงของอะตอม ซึ่งมีการดำเนินการอะตอม
ใช้เริ่มต้นรับประกันเกี่ยวกับการสั่งซื้อของการเข้าถึงหน่วยความจำ เริ่มต้นนี้รับประกัน
มีความสอดคล้องต่อเนื่องกัน ซึ่งหมายความว่า ในหัวข้อ การดำเนินงานของอะตอมจะรับประกัน
เกิดขึ้นในลำดับตามที่ตั้งโปรแกรม ดังนั้น ปัญหาการสั่งเพิ่มงบตามที่แนะนำในส่วน
18.4.3 หน้า 986 , ไม่ได้ใช้ ในตอนท้ายของมาตรานี้ ผมเสนออินเตอร์เฟซระดับ
อะตอม : การผ่อนคลาย
เพื่อการันตีโปรดทราบว่ามาตรฐานห้องสมุดไม่แยกแยะระหว่างอินเตอร์เฟซ
อะตอมระดับสูงและระดับต่ำ . คำ - แนะนำโดยฮันส์โบม หนึ่งในผู้เขียนของห้องสมุด .
บางครั้งก็เรียกว่า อ่อนแอ หรือผ่อนคลาย อะตอมอินเตอร์เฟซและอินเตอร์เฟซระดับสูง
บางครั้งเรียกว่าปกติ หรือแข็งแรง อะตอมเชื่อมต่อ ตัวอย่างของการใช้อะตอม

18.7.1ขอโอนตัวอย่างจากส่วน 18.6.1 หน้า 1002 เป็นโปรแกรมใช้อะตอม :
#รวม > / / < อะตอมอะตอม

. . . . . . . ประเภท : : : อะตอม < บูล > readyflag ( เท็จ ) ; เป็นโมฆะ thread1()

{
/ / ทำ thread2 ความต้องการเตรียม

readyflag ร้าน . . . . . . . . ( จริง ) ;
}
www.it-ebooks ข้อมูล


thread2() 18.7 อะตอม 1013 โมฆะ {
/ / รอจนกว่า readyflag เป็นจริง ( thread1 เสร็จ )
ในขณะที่ ! readyflag . load() ) {
std : :this_thread : : sleep_for ( std : : Chrono : : มิลลิวินาที ( 100 ) ;
}
/ / ทำสิ่งที่จะเกิดขึ้นหลังจาก thread1 ได้เตรียมสิ่งที่
.
}
ก่อนอื่นเรารวมไฟล์ส่วนหัว < > อะตอม ซึ่งอะตอมจะประกาศ :
#รวมอะตอม >
< เราประกาศแล้ว วัตถุอะตอม โดยใช้ std : : อะตอม < > คลาสแม่แบบ :
std : : อะตอม < บูล > readyflag ( เท็จ ) ;
ในหลักการ , คุณสามารถใช้ใด ๆ เล็กน้อย , Integral ,หรือตัวชี้ชนิดพารามิเตอร์ของแม่แบบ
ทราบว่าคุณควรเริ่มต้นวัตถุปรมาณู เพราะจัดสร้างเริ่มต้นไม่ได้
อย่างเต็มที่เริ่มต้น ( ไม่ใช่ค่าเริ่มต้นเป็นภาษาอังกฤษ มันเป็นล็อค uninitialized ) 26
สำหรับระยะเวลาคงที่ของวัตถุ คุณควรใช้อย่างต่อเนื่องเพื่อเริ่มการทำงานของพวกเขา ถ้าแค่เริ่มต้น
คอนสตรัคเตอร์ ใช้การอนุญาตเท่านั้นต่อไปจะเรียกการผ่าตัด atomic_init() ทั่วโลก

: : : 1 อะตอม < บูล > readyflag ;
. .
: : : atomic_init ( & readyflag , เท็จ ) ;
วิธีนี้เริ่มต้นให้สามารถที่จะเขียนโค้ดที่ยังรวบรวมใน C ( ดูมาตรา 18.7.3
, หน้า 1019 )
2 สำคัญที่สุด งบเพื่อจัดการกับอะตอมและมี store() load() :
-
store() กำหนดค่าใหม่บริการ load() ผลผลิต ค่าปัจจุบัน
ประเด็นสำคัญอยู่ที่ว่าการดำเนินงานเหล่านี้จะรับประกันเป็นอะตอม ดังนั้นเราไม่ต้อง mutex
ตั้งธงพร้อม เราก็จะไม่มีอะตอม . ดังนั้น ในหัวข้อแรก แทนที่จะ
{
std : : lock_guard < std : : mutex > LG ( readymutex ) ;
readyflag = true ;
} / / ปล่อยล็อค
เราก็สามารถโปรแกรม :
readyflag ร้าน ( true ) ;
.26 ขอบคุณลอว์เรนซ์ crowl สำหรับชี้ออกนี้ .
www.it-ebooks ข้อมูล
1 บทที่ 18 : การ
ในหัวข้อที่สอง แทนที่จะ
{
std : : unique_lock < std : : mutex > L ( readyflagmutex ) ;
ในขณะที่ ! readyflag ) {
L unlock() ;
: : : : : this_thread sleep_for ( std : : Chrono : : มิลลิวินาที ( 100 ) ;
. lock() ;
}
} / / ปล่อยล็อค
เราต้องใช้ต่อไปนี้เท่านั้น :
ในขณะที่ ! readyflag . load() ) {
this_thread std : : : :sleep_for ( std : : Chrono : : มิลลิวินาที ( 100 ) ; } )

แต่เมื่อใช้ตัวแปรเงื่อนไข เรายังต้องการ mutex สำหรับการบริโภคในเงื่อนไขตัวแปร :

/ / รอจนกว่า thread1 พร้อม ( readyflag เป็นจริง )
{
std : : unique_lock < std : : mutex > L ( readymutex ) ;
readycondvar รอ ( L , [ ] { กลับ readyflag . load() ; } ) ; } / /

อะตอมชนิดสำหรับการปลดล็อค , คุณยังสามารถใช้ " ประโยชน์ " การผ่าตัดปกติ "เช่น การบ้าน , การแปลงอัตโนมัติ
ประเภท , เพิ่มขึ้น , decrements ส่วนประกอบและอื่น ๆ :
std : : อะตอม < บูล > AB ( เท็จ ) ;

ถ้า AB = true ; ( AB ) {

}
std : : . . . . . . . อะตอม < int > AI ( 0 ) ;
1 x = AI AI = 10 ;
;
AI AI = 17 ;
;
หมายเหตุ อย่างไรก็ตาม เพื่อให้ปรมาณู บางพฤติกรรมปกติอาจจะแตกต่างกันเล็กน้อย ตัวอย่างเช่น
ให้ผู้ประกอบการสามารถกำหนดค่าแทนการอ้างอิงถึงอะตอมค่า
ได้รับมอบหมายให้ ดูส่วน 18.7.2 หน้า 1184 , รายละเอียด .
ลองดูตัวอย่างที่สมบูรณ์โดยใช้อะตอม :
/ / /
#พร้อมกัน atomics1 . cpp > / / < อะตอมประกอบด้วยอะตอม
#รวมถึงในอนาคต > / / < async() และล่วงหน้า

www.it-ebooks ข้อมูลมาก
#รวมถึง < ด้ายลองอะตอม > / / this_thread
#รวมถึง < เวลา > / / < iostream > #รวมระยะเวลา

ข้อมูลยาว ;
std : : อะตอม < บูล > readyflag ( เท็จ ) ; ผู้ให้บริการ
เป็นโมฆะ ( )
{
/ / หลังจากอ่านตัวอักษร
std : : เคาท์ " < < < กลับ > " < < std : : Endl ;
std : : ซิน . get() ;
/ / ให้ข้อมูลบางอย่าง
ข้อมูล = 42 ;
/ /
readyflag ความพร้อมและสัญญาณ ร้าน ( true ) ;
}
( )
{ โมฆะผู้บริโภค
/ / รอความพร้อมและทำอย่างอื่น
ในขณะที่ ! readyflag . load() ) {
std : : เคาท์ ใส่ ( ' . ' )flush() ;
: : : : : this_thread sleep_for ( std : : Chrono : : มิลลิวินาที ( 500 ) ) ;
}
/ / และกระบวนการให้ข้อมูล
std : : เคาท์ < < " nvalue " < < ข้อมูล < < std : : Endl ;

{ }

/ / main() นท์ เริ่มต้นผู้ให้บริการและผู้บริโภค
Auto P = std : : Async ( std : : เปิด : : การ ผู้ให้บริการอัตโนมัติ ) ;
c = std : : Async ( std : : เปิด : : การอุปโภคบริโภค ) ;
}
ที่นี่ หัวข้อ provider() แรกแสดงข้อมูลบางส่วนและจากนั้นใช้ store() เพื่อส่งสัญญาณว่า
ข้อมูลบริการข้อมูล :
= 42 ; / / ให้ข้อมูลบางอย่าง
readyflag เก็บจริง ( ) ; / /
www.it-ebooks.info สัญญาณความพร้อม
การแปล กรุณารอสักครู่..
 
ภาษาอื่น ๆ
การสนับสนุนเครื่องมือแปลภาษา: กรีก, กันนาดา, กาลิเชียน, คลิงออน, คอร์สิกา, คาซัค, คาตาลัน, คินยารวันดา, คีร์กิซ, คุชราต, จอร์เจีย, จีน, จีนดั้งเดิม, ชวา, ชิเชวา, ซามัว, ซีบัวโน, ซุนดา, ซูลู, ญี่ปุ่น, ดัตช์, ตรวจหาภาษา, ตุรกี, ทมิฬ, ทาจิก, ทาทาร์, นอร์เวย์, บอสเนีย, บัลแกเรีย, บาสก์, ปัญจาป, ฝรั่งเศส, พาชตู, ฟริเชียน, ฟินแลนด์, ฟิลิปปินส์, ภาษาอินโดนีเซี, มองโกเลีย, มัลทีส, มาซีโดเนีย, มาราฐี, มาลากาซี, มาลายาลัม, มาเลย์, ม้ง, ยิดดิช, ยูเครน, รัสเซีย, ละติน, ลักเซมเบิร์ก, ลัตเวีย, ลาว, ลิทัวเนีย, สวาฮิลี, สวีเดน, สิงหล, สินธี, สเปน, สโลวัก, สโลวีเนีย, อังกฤษ, อัมฮาริก, อาร์เซอร์ไบจัน, อาร์เมเนีย, อาหรับ, อิกโบ, อิตาลี, อุยกูร์, อุสเบกิสถาน, อูรดู, ฮังการี, ฮัวซา, ฮาวาย, ฮินดี, ฮีบรู, เกลิกสกอต, เกาหลี, เขมร, เคิร์ด, เช็ก, เซอร์เบียน, เซโซโท, เดนมาร์ก, เตลูกู, เติร์กเมน, เนปาล, เบงกอล, เบลารุส, เปอร์เซีย, เมารี, เมียนมา (พม่า), เยอรมัน, เวลส์, เวียดนาม, เอสเปอแรนโต, เอสโทเนีย, เฮติครีโอล, แอฟริกา, แอลเบเนีย, โคซา, โครเอเชีย, โชนา, โซมาลี, โปรตุเกส, โปแลนด์, โยรูบา, โรมาเนีย, โอเดีย (โอริยา), ไทย, ไอซ์แลนด์, ไอร์แลนด์, การแปลภาษา.

Copyright ©2024 I Love Translation. All reserved.

E-mail: