pthread在语句中使用的互斥锁定变量

时间:2016-05-10 09:07:05

标签: c linux pthreads posix mutex

首先,我有一种直觉,在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);

第二个问题,如果我确实需要锁定它,我应该如何以优雅的程序员方式进行操作?换句话说,什么是一般惯例。我不喜欢以下的想法,因为我必须等待内部的所有线路,如果"执行以便能够再次解锁互斥锁。

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
}

3 个答案:

答案 0 :(得分:4)

是的,您需要同步所有读取。

对于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);

..所以锁总是保持在这种状态。

答案 1 :(得分:3)

是的,在读取或写入受保护变量之前,应始终锁定互斥锁。为了避免混乱的代码,同时仍然最小化锁定时间,您应该将事件信息移动到可以在互斥锁解锁后使用的本地变量,如此

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
}

答案 2 :(得分:3)

应该保护对共享变量的每次访问 - 写入和读取。你通过互斥体包围多少其他东西 - 平衡开销,使用变量的原子性和代码清晰度。

此外,您不想在保护区内花费很长时间,因此如果您在长段代码中同步变量两次,则不想锁定整个大部分限制。

某些阅读显然存在问题:

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.

在这种情况下,保留不同的“同步区域”并在变量的本地副本上运行会好得多。

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);

等等。

频繁使用给定变量的方式不需要病房,没有忘记解锁的风险(如缺乏其他'否则'声明!)并捆绑工作,最大限度地减少在互斥锁中等待或锁定/解锁它们所花费的时间。

还要记住:不要丢失要缓存的同步数据,所有线程间变量都应声明为volatile。否则,event从一个线程传播到另一个线程可能需要很长时间。但是使用volatile会使编译器破坏很多优化。通过制作非易失性本地副本,您可以减少围绕volatile变量完成的工作量,并允许优化器遍布整个副本,而不会有破坏的风险。