语句中使用的 pthread 互斥锁定变量
pthread mutex locking variables used in statements
首先,我有一种直觉说,在 if 语句中,如果我正在使用变量,它算作读取变量,所以我也应该用互斥量锁定它(如果另一个 pthread 可能是用它做事)。我应该锁定它是对的吗?
下面给出简化的示例情况。
在一个线程中,我使用以下语句:
if(event){
// Should I or should I not lock event here to use it
// inside if statement?
pthread_mutex_lock(&mutex_event);
event = 0;
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
}
在我正在做的另一个线程中
pthread_mutex_lock(&mutex_event);
event = 1;
pthread_mutex_unlock(&mutex_event);
第二个问题,如果我确实需要锁定它,我应该如何以优雅的程序员方式进行?换句话说,什么是通用约定。我不喜欢下面的想法,因为我必须等待 "if" 中的所有行执行才能再次解锁互斥量。
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
// blah blah code here
// blah blah code here
// blah blah code here
}
pthread_mutex_unlock(&mutex_event);
我同意这个想法,但它可能看起来更漂亮:
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
}
else
{
pthread_mutex_unlock(&mutex_event);
}
我发现 while 循环会变得更棘手,这是我得到的原始解决方案:
pthread_mutex_lock(&mutex_event);
store_event = event; // store_event is local
pthread_mutex_unlock(&mutex_event);
while(store_event){
// blah blah code here
// blah blah code here
// blah blah code here
}
是的,您应该始终在读取或写入受保护变量之前锁定互斥量。为了避免乱码,同时尽量减少锁定时间,你应该将事件信息移动到一个局部变量中,以便在互斥体解锁后使用,像这样
int do_blah = 0;
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
do_blah = 1;
}
pthread_mutex_unlock(&mutex_event);
if ( do_blah ) {
// blah blah code here
// blah blah code here
// blah blah code here
}
对共享变量的每次 访问——写和读——都应该受到保护。互斥量还有多少是一个单独的问题 - 平衡开销、使用变量的原子性和代码的清晰度。
另外,你不想在保护区停留很长时间,所以如果你在一段很长的代码中对一个变量进行两次同步,你也不想锁定整个大段代码。
有些读取明显有问题:
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
}
else pthread_mutex_unlock(&mutex_event); //awful, a hundred lines below the opening.
在这种情况下,最好保留不同 'synchronization zones',并在变量的本地副本上进行操作。
pthread_mutex_lock(&mutex_event);
event_copy = event;
data_copy = data;
state_copy = state;
pthread_mutex_unlock(&mutex_event);
if(event_copy){
// blah blah code here
// blah blah code here
event_copy = 0;
// blah blah code here
}
// blah blah code here
pthread_mutex_lock(&mutex_event);
event = event_copy;
data = data_copy;
state = state_copy;
pthread_mutex_unlock(&mutex_event);
等等。
这样经常使用给定变量不需要病房,没有忘记解锁的风险(比如缺少那个'else'声明!)和您将工作捆绑在一起,最大限度地减少在互斥体或 locking/unlocking 中等待的时间。
还要记住:为了不丢失同步数据缓存,所有线程间变量都应该声明为volatile
。否则,您的 event
可能需要很长时间才能从一个线程传播到另一个线程。但是使用 volatile
你会破坏编译器的很多优化。通过制作非易失性本地副本,您可以减少围绕易失性变量完成的工作量,并允许优化器在所有副本上发挥作用而不会破坏事物。
是的,您确实需要对所有读取进行同步。
对于 while()
循环,您可以使用此模式:
pthread_mutex_lock(&mutex_event);
while(event) {
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
pthread_mutex_lock(&mutex_event);
}
pthread_mutex_unlock(&mutex_event);
..因此锁始终保持在条件下。
首先,我有一种直觉说,在 if 语句中,如果我正在使用变量,它算作读取变量,所以我也应该用互斥量锁定它(如果另一个 pthread 可能是用它做事)。我应该锁定它是对的吗?
下面给出简化的示例情况。
在一个线程中,我使用以下语句:
if(event){
// Should I or should I not lock event here to use it
// inside if statement?
pthread_mutex_lock(&mutex_event);
event = 0;
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
}
在我正在做的另一个线程中
pthread_mutex_lock(&mutex_event);
event = 1;
pthread_mutex_unlock(&mutex_event);
第二个问题,如果我确实需要锁定它,我应该如何以优雅的程序员方式进行?换句话说,什么是通用约定。我不喜欢下面的想法,因为我必须等待 "if" 中的所有行执行才能再次解锁互斥量。
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
// blah blah code here
// blah blah code here
// blah blah code here
}
pthread_mutex_unlock(&mutex_event);
我同意这个想法,但它可能看起来更漂亮:
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
}
else
{
pthread_mutex_unlock(&mutex_event);
}
我发现 while 循环会变得更棘手,这是我得到的原始解决方案:
pthread_mutex_lock(&mutex_event);
store_event = event; // store_event is local
pthread_mutex_unlock(&mutex_event);
while(store_event){
// blah blah code here
// blah blah code here
// blah blah code here
}
是的,您应该始终在读取或写入受保护变量之前锁定互斥量。为了避免乱码,同时尽量减少锁定时间,你应该将事件信息移动到一个局部变量中,以便在互斥体解锁后使用,像这样
int do_blah = 0;
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
do_blah = 1;
}
pthread_mutex_unlock(&mutex_event);
if ( do_blah ) {
// blah blah code here
// blah blah code here
// blah blah code here
}
对共享变量的每次 访问——写和读——都应该受到保护。互斥量还有多少是一个单独的问题 - 平衡开销、使用变量的原子性和代码的清晰度。
另外,你不想在保护区停留很长时间,所以如果你在一段很长的代码中对一个变量进行两次同步,你也不想锁定整个大段代码。
有些读取明显有问题:
pthread_mutex_lock(&mutex_event);
if(event){
event = 0;
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
}
else pthread_mutex_unlock(&mutex_event); //awful, a hundred lines below the opening.
在这种情况下,最好保留不同 'synchronization zones',并在变量的本地副本上进行操作。
pthread_mutex_lock(&mutex_event);
event_copy = event;
data_copy = data;
state_copy = state;
pthread_mutex_unlock(&mutex_event);
if(event_copy){
// blah blah code here
// blah blah code here
event_copy = 0;
// blah blah code here
}
// blah blah code here
pthread_mutex_lock(&mutex_event);
event = event_copy;
data = data_copy;
state = state_copy;
pthread_mutex_unlock(&mutex_event);
等等。
这样经常使用给定变量不需要病房,没有忘记解锁的风险(比如缺少那个'else'声明!)和您将工作捆绑在一起,最大限度地减少在互斥体或 locking/unlocking 中等待的时间。
还要记住:为了不丢失同步数据缓存,所有线程间变量都应该声明为volatile
。否则,您的 event
可能需要很长时间才能从一个线程传播到另一个线程。但是使用 volatile
你会破坏编译器的很多优化。通过制作非易失性本地副本,您可以减少围绕易失性变量完成的工作量,并允许优化器在所有副本上发挥作用而不会破坏事物。
是的,您确实需要对所有读取进行同步。
对于 while()
循环,您可以使用此模式:
pthread_mutex_lock(&mutex_event);
while(event) {
pthread_mutex_unlock(&mutex_event);
// blah blah code here
// blah blah code here
// blah blah code here
pthread_mutex_lock(&mutex_event);
}
pthread_mutex_unlock(&mutex_event);
..因此锁始终保持在条件下。