ฉันกำลังมองหาตัวล็อคผู้อ่าน / นักเขียนที่ดีใน C ++ เรามีกรณีการใช้งานของผู้เขียนไม่บ่อยเพียงคนเดียวและผู้อ่านบ่อยจำนวนมาก และต้องการเพิ่มประสิทธิภาพเพื่อสิ่งนี้ จะดีกว่า ฉันต้องการโซลูชันข้ามแพลตฟอร์ม อย่างไรก็ตาม Windows มีเพียงระบบเดียวเท่านั้นที่ยอมรับได้
Reader/Writer ล็อคใน C ++
คำตอบ (12)
boost::thread เวอร์ชันใหม่กว่ามีการอ่าน/เขียนแล้ว ล็อค (1.35.0 และใหม่กว่า เห็นได้ชัดว่าเวอร์ชันก่อนหน้าทำงานไม่ถูกต้อง)
พวกเขามีชื่อ shared_lock
, unique_lock
และ upgrade_lock
และดำเนินการบน shared_mutex
.
shared_timed_mutex
และ shared_lock
ที่ตรงกัน
- person Jan Kundrát; 22.10.2018
ตั้งแต่ C ++ 17 (VS2015) คุณสามารถใช้มาตรฐาน:
#include <shared_mutex>
typedef std::shared_mutex Lock;
typedef std::unique_lock< Lock > WriteLock;
typedef std::shared_lock< Lock > ReadLock;
Lock myLock;
void ReadFunction()
{
ReadLock r_lock(myLock);
//Do reader stuff
}
void WriteFunction()
{
WriteLock w_lock(myLock);
//Do writer stuff
}
สำหรับคอมไพเลอร์เวอร์ชันเก่าและมาตรฐาน คุณสามารถใช้ boost เพื่อสร้างการล็อกการอ่าน-เขียน:
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
typedef boost::shared_lock< Lock > ReadLock;
การใช้สิ่งที่สร้างไว้ล่วงหน้าแบบมาตรฐานที่ทดสอบไว้ล่วงหน้านั้นดีเสมอ (เช่น Boost เป็นคำตอบอื่นที่แนะนำ) แต่นี่เป็นสิ่งที่ไม่ยากเกินไปที่จะสร้างด้วยตัวเอง นี่คือการใช้งานเล็ก ๆ น้อย ๆ ที่โง่เขลาที่ดึงออกมาจากโครงการของฉัน:
#include <pthread.h>
struct rwlock {
pthread_mutex_t lock;
pthread_cond_t read, write;
unsigned readers, writers, read_waiters, write_waiters;
};
void reader_lock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
if (self->writers || self->write_waiters) {
self->read_waiters++;
do pthread_cond_wait(&self->read, &self->lock);
while (self->writers || self->write_waiters);
self->read_waiters--;
}
self->readers++;
pthread_mutex_unlock(&self->lock);
}
void reader_unlock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
self->readers--;
if (self->write_waiters)
pthread_cond_signal(&self->write);
pthread_mutex_unlock(&self->lock);
}
void writer_lock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
if (self->readers || self->writers) {
self->write_waiters++;
do pthread_cond_wait(&self->write, &self->lock);
while (self->readers || self->writers);
self->write_waiters--;
}
self->writers = 1;
pthread_mutex_unlock(&self->lock);
}
void writer_unlock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
self->writers = 0;
if (self->write_waiters)
pthread_cond_signal(&self->write);
else if (self->read_waiters)
pthread_cond_broadcast(&self->read);
pthread_mutex_unlock(&self->lock);
}
void rwlock_init(struct rwlock *self) {
self->readers = self->writers = self->read_waiters = self->write_waiters = 0;
pthread_mutex_init(&self->lock, NULL);
pthread_cond_init(&self->read, NULL);
pthread_cond_init(&self->write, NULL);
}
pthreads
ไม่ใช่ Windows จริงๆ แต่แนวคิดทั่วไปอยู่ที่นี่ การใช้งานนี้มีอคติต่อนักเขียนเล็กน้อย (นักเขียนจำนวนมากสามารถทำให้ผู้อ่านอดอยากได้อย่างไม่มีกำหนด) เพียงแก้ไข writer_unlock
หากคุณต้องการให้ความสมดุลเป็นอย่างอื่น
ใช่ นี่คือ C ไม่ใช่ C++ การแปลเป็นแบบฝึกหัดที่เหลือสำหรับผู้อ่าน
แก้ไข
Greg Rogers ชี้ให้เห็นว่ามาตรฐาน POSIX ระบุ pthread_rwlock_*
สิ่งนี้ไม่ได้ช่วยอะไรถ้าคุณไม่มี pthreads
แต่มันทำให้ฉันนึกถึง: Pthreads-w32 ก> ควรจะได้ผล! แทนที่จะย้ายรหัสนี้เป็น non-pthreads
สำหรับการใช้งานของคุณเอง เพียงใช้ Pthreads-w32 บน Windows และเนทิฟ pthreads
ทุกที่
while
แก้ไข do pthread_cond_wait
บนบรรทัดที่อยู่ด้านบนทันที ไม่มีข้อยกเว้นในภาษา C (จริงอยู่ ฉันไม่จัดการกับเงื่อนไขข้อผิดพลาด แต่นั่นไม่ใช่ข้อยกเว้น)
- person ephemient; 28.10.2008
writer_unlock
หากคุณต้องการให้ความสมดุลเป็นอย่างอื่น
- person ephemient; 11.01.2010
ไม่ว่าคุณจะตัดสินใจใช้อะไรก็ตาม ให้เปรียบเทียบภาระงานของคุณกับล็อคแบบธรรมดา เนื่องจากการล็อคการอ่าน/เขียนมักจะช้ากว่า mutex แบบธรรมดา 3-40 เท่า เมื่อไม่มีการโต้แย้ง
นี่คือข้อมูลอ้างอิงบางส่วน
แก้ไข: ลิงก์ MSDN Magazine ไม่สามารถใช้งานได้อีกต่อไป บทความ CodeProject มีอยู่ใน https://www.codeproject.com/Articles/32685/Testing-reader-writer-locks และสรุปได้ค่อนข้างดี นอกจากนี้ ฉันยังพบลิงก์ MSDN ใหม่เกี่ยวกับ Compound Synchronization Objects
มีบทความเกี่ยวกับการล็อกตัวอ่านและผู้เขียนบน MSDN ที่นำเสนอบางส่วน การใช้งานของพวกเขา นอกจากนี้ยังแนะนำ Slim reader/writer lock ซึ่งเป็นการซิงโครไนซ์เคอร์เนลแบบดั้งเดิมที่นำมาใช้กับ Vista นอกจากนี้ยังมีบทความ CodeProject เกี่ยวกับการเปรียบเทียบการใช้งานที่แตกต่างกัน (รวมถึงบทความ MSDN ด้วย) .
C++17 รองรับ std::shared_mutex
รองรับใน MSVC++ 2015 และ 2017 .
Intel Thread Building Blocks ยังมี rw_lock ให้เลือกสองสามแบบ:
http://www.threadingbuildingblocks.org/
พวกมันมี spin_rw_mutex สำหรับช่วงการโต้แย้งที่สั้นมาก และ Queuing_rw_mutex สำหรับช่วงการโต้แย้งที่นานกว่า แบบแรกสามารถนำมาใช้ในโค้ดที่คำนึงถึงประสิทธิภาพโดยเฉพาะ อย่างหลังนั้นเทียบเคียงได้ดีกว่าในด้านประสิทธิภาพกับที่ได้รับจาก Boost.Thread หรือใช้ pthreads โดยตรง แต่โปรไฟล์เพื่อให้แน่ใจว่าอันไหนชนะสำหรับรูปแบบการเข้าถึงของคุณ
Boost.Thread มีตั้งแต่เปิดตัว 1.35.0 แล้ว รองรับการล็อคผู้อ่านและนักเขียน สิ่งที่ดีเกี่ยวกับเรื่องนี้ก็คือ การใช้งานเป็นแบบข้ามแพลตฟอร์มอย่างมาก มีการตรวจสอบโดยผู้ทรงคุณวุฒิ และจริงๆ แล้ว การใช้งานอ้างอิงสำหรับมาตรฐาน C++0x ที่กำลังจะมาถึง
ฉันขอแนะนำ ไลบรารี ACE ซึ่งมีกลไกการล็อกมากมายและ ถูกพอร์ตไปยังแพลตฟอร์มต่างๆ
ขึ้นอยู่กับเงื่อนไขขอบเขตของปัญหาของคุณ คุณอาจพบว่าคลาสต่อไปนี้มีประโยชน์:
ACE_RW_Process_Mutex
ACE_Write_Guard
และACE_Read_Guard
ACE_Condition
http://www.codeproject.com/KB/threads/ReaderWriterLock.aspx
นี่คือการใช้งานที่ดีและไม่ซับซ้อนซึ่งเหมาะสำหรับงานส่วนใหญ่
คลาสล็อคการซิงโครไนซ์ตัวอ่านหลายตัวและนักเขียนเดี่ยวสำหรับ Win32 โดย Glenn Slayde
http://www.glennslayden.com/code/win32/reader-writer-lock
คุณสามารถคัดลอก ReentrantReadWriteLock ที่ยอดเยี่ยมของ Sun ได้. มันมีฟีเจอร์ต่างๆ เช่น ความเป็นธรรมที่เป็นตัวเลือก การดาวน์เกรดการล็อก และการกลับเข้าใหม่
ใช่ มันอยู่ใน Java แต่คุณสามารถอ่านและแปลงเป็น C++ ได้อย่างง่ายดาย แม้ว่าคุณจะไม่รู้จัก Java ก็ตาม เอกสารประกอบที่ฉันเชื่อมโยงไปนั้นมีคุณสมบัติด้านพฤติกรรมทั้งหมดของการใช้งานนี้ ดังนั้นคุณจึงมั่นใจได้ว่ามันจะเป็นไปตามที่คุณต้องการ
ถ้าไม่มีอะไรก็เป็นแนวทาง
finally
ดังนั้นการแปลโดยตรงจาก Java เป็น C++ จึงเป็นความคิดที่ไม่ดีเมื่อมีข้อยกเว้น
- person Tom; 23.01.2010