Dav*_*vid 7 c locking pthreads thread-safety
I need to control the frequency at which main processes data. In the example, it just increases the value of a variable. I cannot use sleep inside of main because I need the frequency to be constant (and I don't know exactly how long does it take to process all the data). I just know for a fact that whatever processing I need to do takes less than 2 seconds, so I just need to prevent main from increasing x more than once every two seconds.
The solution I've found involves using two mutexes: locking one in main and unlocking it in an extra thread, and locking the other in extra and unlocking it in main. This extra thread sleeps for 2 seconds per cycle.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *extra(void *arg)
{
pthread_mutex_t *lock = (pthread_mutex_t *) arg;
while(1) {
pthread_mutex_unlock(&lock[0]);
pthread_mutex_lock(&lock[1]);
sleep(2);
}
}
int main()
{
int x = 0;
pthread_mutex_t lock[2];
pthread_mutex_init(&lock[0], NULL);
pthread_mutex_init(&lock[1], NULL);
pthread_mutex_lock(&lock[1]);
pthread_t extra_thread;
pthread_create(&extra_thread, NULL, &extra, lock);
while(1) {
x += 1;
printf("%d\n", x);
pthread_mutex_lock(&lock[0]);
pthread_mutex_unlock(&lock[1]);
}
}
Run Code Online (Sandbox Code Playgroud)
The reason why this works is that main cannot lock lock[0] twice; it has to wait until extra unlocks it. However, according to The Open Group
Attempting to relock the mutex causes deadlock. If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, undefined behavior results.
Based on this, I see two issues here:
main tries to lock lock[0] twice it should deadlock.extra unlocking lock[0], which was locked by main, should be undefined behavior.Is my analysis correct?
回答您的问题,
- 如果
main尝试锁定lock[0]两次,则应死锁。
是的,会的。除非您使用递归互斥锁,否则您的子线程将永远无法像main总是将其锁定那样来锁定互斥锁。
extra解锁lock[0],这是由主锁,应该是未定义的行为。
按照POSIX文档pthread_mutex_unlock(),这是一个不确定的行为NORMAL 和非稳健的互斥。但是,DEFAULT互斥对象不必一定NORMAL是非稳健的,因此有一个警告:
如果互斥锁类型为
PTHREAD_MUTEX_DEFAULT,则pthread_mutex_lock()[和pthread_mutex_unlock()] 的行为可能对应于上表中所述的其他三个标准互斥锁类型之一。如果它不符合这三个条件之一,则对于标记的情况,行为是不确定的。
(请注意我的补充pthread_mutex_unlock()。互斥锁行为表清楚地表明,非所有者的解锁行为在不同类型的互斥锁之间有所不同,甚至在“非所有者时解锁”列中使用与“重新锁定”列,“匕首”标记是指我引用的脚注。)
如果非所有者线程尝试对其进行解锁,则健壮的NORMAL,ERRORCHECK或RECURSIVE互斥锁将返回错误,并且互斥锁保持锁定状态。
一个更简单的解决方案是使用一对信号量(以下代码故意缺少错误检查以及空行,否则它们将提高可读性,从而消除/减少任何垂直滚动条):
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
sem_t main_sem;
sem_t child_sem;
void *child( void *arg )
{
for ( ;; )
{
sem_wait( &child_sem );
sleep( 2 );
sem_post( &main_sem );
}
return( NULL );
}
int main( int argc, char **argv )
{
pthread_t child_tid;
sem_init( &main_sem, 0, 0 );
sem_init( &child_sem, 0, 0 );
pthread_create( &child_tid, NULL, child, NULL );
int x = 0;
for ( ;; )
{
// tell the child thread to go
sem_post( &child_sem );
// wait for the child thread to finish one iteration
sem_wait( &main_sem );
x++;
printf("%d\n", x);
}
pthread_join( child_tid, NULL );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |