rak*_*esh 4 c++ multithreading mutex pthreads
我试图仅使用互斥锁实现读/写锁定(仅用于学习).就在我认为我已经覆盖所有角落的情况下(因为程序使用各种组合),我已经意识到,我忽略了事实(因为它在ubuntu中工作),互斥体应该由线程的所有者释放.以下是我的实施,
class rw_lock_t{
int NoOfReaders;
int NoOfWriters, NoOfWritersWaiting;
pthread_mutex_t class_mutex;
pthread_cond_t class_cond;
pthread_mutex_t data_mutex;
public:
rw_lock_t()
: NoOfReaders(0),
NoOfWriters(0), NoOfWritersWaiting(0)
{
pthread_mutex_init(&class_mutex, NULL);
pthread_mutex_init(&data_mutex, NULL);
pthread_cond_init(&class_cond, NULL);
}
void r_lock()
{
pthread_mutex_lock(&class_mutex);
//while(NoOfWriters!=0 || NoOfWritersWaiting!=0) //Writer Preference
while(NoOfWriters!=0)
{
pthread_cond_wait(&class_cond, &class_mutex);
}
if(NoOfReaders==0)
{
pthread_mutex_unlock(&class_mutex);
pthread_mutex_lock(&data_mutex);
pthread_mutex_lock(&class_mutex);
NoOfReaders++;
pthread_mutex_unlock(&class_mutex);
}
else if(NoOfReaders>0) //Already Locked
{
NoOfReaders++;
pthread_mutex_unlock(&class_mutex);
}
}
void w_lock()
{
pthread_mutex_lock(&class_mutex);
NoOfWritersWaiting++;
while(NoOfReaders!=0 && NoOfWriters!=0)
{
pthread_cond_wait(&class_cond, &class_mutex);
}
pthread_mutex_unlock(&class_mutex);
pthread_mutex_lock(&data_mutex);
pthread_mutex_lock(&class_mutex);
NoOfWritersWaiting--; NoOfWriters++;
pthread_mutex_unlock(&class_mutex);
}
void r_unlock()
{
pthread_mutex_lock(&class_mutex);
NoOfReaders--;
if(NoOfReaders==0)
pthread_mutex_unlock(&data_mutex);
pthread_mutex_unlock(&class_mutex);
pthread_cond_signal(&class_cond);
}
void w_unlock()
{
pthread_mutex_lock(&class_mutex);
NoOfWriters--;
if(NoOfWriters==0)
pthread_mutex_unlock(&data_mutex);
pthread_mutex_unlock(&class_mutex);
pthread_cond_signal(&class_cond);
}
};
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,纠正的最佳方式(最小变化)是什么.信号量肯定是空闲的选择,但我想到的解决方案如下
解决方案#1
1)我将有一个专用线程,只是为了读取案例锁定/解锁互斥锁.
2)此线程将等待条件变量以从r_lock或r_unlock获取信号.
3)r_lock和r_unlock将代替执行"pthread_mutex_lock/unlock(&data_mutex);",将发信号通知专用线程锁定.
4)我必须记住这个实现的许多事实,
信令和实际锁定是两个不同的事件,因此可能需要同步.
将需要一个互斥+ condVariable +线程和更多的同步额外.
更新:解决方案#2
1)执行实际锁定的线程将全局保持其tid.
2)每当线程解锁时,将确保检查与全局tid相等.
3)如果匹配将等待"NoOfReaders == 0"条件并解锁它.
那么,是否有更好的方法可以纠正该计划.
您不需要单独的互斥锁"用于数据"; 如果内部逻辑正确,则整个构造将用作数据锁.相反,您可以为读者和作者使用两个单独的条件变量,这样您就可以广播所有等待的读者而不会影响等待的编写者.代码如下; 你也可以看到这种方式更简单.此外,我添加了一个析构函数并在w_lock中修复了一个错误:等待的条件应该是 (NoOfReaders!=0 || NoOfWriters!=0),而不是&&.
class rw_lock_t {
int NoOfReaders;
int NoOfWriters, NoOfWritersWaiting;
pthread_mutex_t class_mutex;
pthread_cond_t reader_gate;
pthread_cond_t writer_gate;
public:
rw_lock_t()
: NoOfReaders(0), NoOfWriters(0), NoOfWritersWating(0),
class_mutex(PTHREAD_MUTEX_INITIALIZER),
reader_gate(PTHREAD_COND_INITIALIZER),
writer_gate(PTHREAD_COND_INITIALIZER)
{}
~rw_lock_t()
{
pthread_mutex_destroy(&class_mutex);
pthread_cond_destroy(&reader_gate);
pthread_cond_destroy(&writer_gate);
}
void r_lock()
{
pthread_mutex_lock(&class_mutex);
//while(NoOfWriters>0 || NoOfWritersWaiting>0) //Writer Preference
while(NoOfWriters>0)
{
pthread_cond_wait(&reader_gate, &class_mutex);
}
NoOfReaders++;
pthread_mutex_unlock(&class_mutex);
}
void w_lock()
{
pthread_mutex_lock(&class_mutex);
NoOfWritersWaiting++;
while(NoOfReaders>0 || NoOfWriters>0)
{
pthread_cond_wait(&writer_gate, &class_mutex);
}
NoOfWritersWaiting--; NoOfWriters++;
pthread_mutex_unlock(&class_mutex);
}
void r_unlock()
{
pthread_mutex_lock(&class_mutex);
NoOfReaders--;
if(NoOfReaders==0 && NoOfWritersWaiting>0)
pthread_cond_signal(&writer_gate);
pthread_mutex_unlock(&class_mutex);
}
void w_unlock()
{
pthread_mutex_lock(&class_mutex);
NoOfWriters--;
if(NoOfWritersWaiting>0)
pthread_cond_signal(&writer_gate);
//else //Writer Preference - don't signal readers unless no writers
pthread_cond_broadcast(&reader_gate);
pthread_mutex_unlock(&class_mutex);
}
};
Run Code Online (Sandbox Code Playgroud)