2011-03-15 98 views
3

我正在创建一个使用双缓冲的线程化应用程序,我试图避免潜在的死锁。主要思想是交换缓冲区线程锁定写入和读取线程。然而,交换缓冲区线程很快,所以锁不会长时间保持锁定状态。写入和读取线程较慢,但高效共享时间片(目标),因为它们锁定在不同的互斥锁上。我的问题是这种设计有潜在的僵局吗?C双缓冲区实现死锁?

  • 3线程...线程A,线程B,和C.螺纹
  • 2互斥...前互斥和后退的互斥。

  • 线程A填充后缓冲器
  • 线程B交换缓冲器。
  • 线程C使用前端缓冲区。

  • 线程A需要theBackMutex,填充后缓冲,释放theBackMutex。
  • 线程C使用FrontMutex,使用前台缓冲区,释放FrontMutex。
  • 线程B需要theBackMutex,theFrontMutex,切换缓冲区,释放theBackMutex,释放theFront互斥

void *fill_back_buffer() { 
    while(1) { 
     if (0 != pthread_mutex_lock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //should we get new data for back buffer? 
     pthread_cond_wait(&theBackBufferRefresh, &theBackMutex); 
     //fill back buffer 
     if (0 != pthread_mutex_unlock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //hey we done filling the back buffer! 
     pthread_cond_signal(&theBackBufferFull); 
    } 
} 


void *swap_buffers() { 
    while(1) { 
     if (0 != pthread_mutex_lock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     if (0 != pthread_mutex_lock(&theFrontkMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //do we have new data in the back buffer? 
     pthread_cond_wait(&theBackBufferFull, &theBackMutex); 

     //swap buffers 
     char* tmp; 
     tmp = theBufferAPtr; 
     theBufferAPtr = theBufferBPtr; 
     theBufferBPtr = tmp; 

     if (0 != pthread_mutex_unlock(&theFrontMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     if (0 != pthread_mutex_unlock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //hey please get more data! 
     pthread_cond_signal(&theBackBufferRefresh); 
     //hey you can use front buffer now! 
     pthread_cond_signal(&theBufferSwapped); 

    } 
} 

int main(int argc, char *argv[]) { 
    //initial fill of the back buffer 
    pthread_cond_signal(&theBackBufferRefresh); 
    while(1) { 
     if (0 != pthread_mutex_lock(&theFrontMutex)) { 
       perror("Mutex lock failed (!!):"); 
       exit(-1); 
     } 
     pthread_cond_wait(&theBufferSwapped, &theFrontMutex); 
     //use the front buffer and do stuff with it 
     if (0 != pthread_mutex_unlock(&theFrontMutex)) { 
       perror("Mutex lock failed (!!):"); 
       exit(-1); 
     } 
    } 
} 
+0

如果你不能工作,我们自己然后建立一个Petri网模型,并检查它的方式。 – 2011-03-15 20:17:45

+0

我会检查一下,我以前从未使用过Petri网模型。谢谢。 – 2011-03-15 20:27:36

+0

一旦你建立了你的模型,你可以将它导入到一个工具,并让工具找到你的死锁。漂亮的东西! – 2011-03-15 20:29:22

回答

2

条件变量应该用来表示某些(互斥锁保护的)共享数据的状态变化。你不能单独使用它们。考虑一下如果一个线程在另一个线程等待这个条件之前发出一个条件,会发生什么情况。

+0

啊,我现在看到了。我只在需要发信号并等待状态改变时才将它们用作信号。 – 2011-03-25 06:21:37

1

我没有看到你创建的线程。我会假设你创建了线程。

swap_buffers()fill_back_buffer()确实包含经典的死锁实现。当swap_buffers()正在等待theBackBufferFull时,它已锁定theBackMutex。同时,fill_back_buffer()正在等待theBackMutex,然后它设置信号theBackBufferFull。因此,theBackBufferFull将永远不会被发信号,因为theBackMutex不能被释放。这是典型的死锁情况。

+0

是的,我没有包括整个代码示例,只是想法。所以当2个线程试图锁定相同的互斥锁时,会造成死锁?我认为它更聪明,只会阻止它最终跳出来。 – 2011-03-15 20:29:54

+0

你应该阅读关于死锁。这并不是说你有两个线程锁定同一个互斥锁 - 问题是你有两个线程阻塞相同的TWO同步原语,互斥锁和信号,并且它们以相反的顺序进行阻塞,导致死锁。可以使用无死锁的互斥锁,但这不是你的问题。你有僵局吗?是的,特别是我描述的地方。 – 2011-03-15 20:34:00

+0

我的理解是条件变量释放它们的互斥量,所以我没有看到你指的是死锁。 – ninjalj 2011-03-15 21:10:52

0

尽量不使用额外的线程进行交换。

+0

是的,我想我可以添加交换到填充缓冲区线程。也许这会让它变得更简单。 – 2011-03-15 20:30:59

+0

这样做有两个线程的“正常”方式,但如果不以正确的顺序锁定,这将无济于事。 – 2011-03-15 20:34:31