2009-08-03 80 views
2

得到假设我有3个POSIX线程一个C程序,共享的全局变量,互斥锁,和条件变量,其中两个是执行以下伪码:保证与调用pthread_cond_wait和调用pthread_cond_signal

...process data... 
pthread_mutex_lock(&mutex); 
variable = data_ptr; 
pthread_cond_signal(&cond); 
pthread_mutex_unlock(&mutex); 

而第三个运行:

while(1) { 
    while(variable == NULL) { 
     pthread_mutex_wait(&cond, &mutex); 
    } 
    printf("Data is %d", *variable); 
} 

它是安全的假设,第三个线程会看到从每个前两个数据?

换一种方式,如果一个线程在互斥锁和条件变量上流水,可以安全地假设它是下一个获取锁的信号,而不是其他某个线程在等待锁?

回答

12

有没有这样的事情pthread_mutex_wait。我假设你的意思是:

pthread_mutex_lock(&mutex); 
/* ... */ 
while (1) { 
    while (variable == NULL) 
    pthread_cond_wait(&cond, &mutex); 
    printf("Data is %d", *variable); 
} 
/* ... */ 
pthread_mutex_unlock(&mutex); 

没有保证第三个线程会看到来自两者的数据。 pthread_cond_signal会唤醒第三个线程,但它可能不会立即采用该互斥锁。其他作家之一可能会先接受互斥体。然而,你可以acheive你想要的东西多一点的工作:

void put(int *p) { 
    pthread_mutex_lock(&mutex); 
    while (variable) 
    pthread_cond_wait(&cond_empty, &mutex); 
    variable = p; 
    pthread_cond_signal(&cond_full); 
    pthread_mutex_unlock(&mutex); 
} 

int *get() { 
    int *ret; 

    pthread_mutex_lock(&mutex); 
    while (!variable) 
    pthread_cond_wait(&cond_full, &mutex); 
    ret = variable; 
    variable = NULL; 
    pthread_cond_signal(&cond_empty); 
    pthread_mutex_unlock(&mutex); 

    return ret; 
} 

通过明确等待要读取的变量,我们避免了潜在的竞争条件。

+0

哎呀,是的,它应该是pthread_cond_wait。 – Edward 2009-08-03 15:20:33

1

以下是我在standard发现:

4.13调度策略

的调度策略影响的进程或线程排序:

[...]

  • 当进程或线程被阻塞的线程并且它变成可运行的线程时

符合实现应该定义每个调度策略可以修改优先级或以其他方式影响上面列出的每个事件的进程或线程的排序的方式。另外,符合实现应该定义在其他情况下以及以何种方式每个调度策略可以修改优先级或影响进程或线程的排序。

所以它显然是未定义的。这并不奇怪:一般来说,您不能假设任何有关可运行线程将被安排运行的任何信息。

0

按照pthread_cond_wait手册页

是畅通应当根据调度策略(如果适用的话),用于互斥抗衡线程(多个),并如同每个都称为pthread_mutex_lock()。

不幸的是,据我所知,没有可用的调度策略给你你想要的行为。

+2

严格地说,单处理器系统上的SCHED_FIFO或SCHED_RR具有比写入器线程更高的静态优先级。但是在SMP上,你仍然可以争夺锁定。 – bdonlan 2009-08-03 15:15:07