使用互斥锁和条件变量调度多线程
Scheduling of Multiple Threads using Mutex and Condition Variable
我正在尝试创建四个线程来打印一些消息。
我在同步方面遇到了一些问题。
这是我的 main()
的样子
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int count = 4;
int main (void)
{
pthread_t thread1, thread2, thread3, thread4;
pthread_create (&thread4, NULL, function4, NULL);
pthread_create (&thread3, NULL, function3, NULL);
pthread_create (&thread2, NULL, function2, NULL);
pthread_create (&thread1, NULL, function1, NULL);
pthread_join (thread1, NULL);
pthread_join (thread2, NULL);
pthread_join (thread3, NULL);
pthread_join (thread4, NULL);
return 0;
}
function1()
打印 Function 1
,function2()
打印 Function 2
等等。
所需的输出应如下所示:
Function 1
Function 2
Function 3
Function 4
实际输出:
Function 1
/* Infinitely runs (Deadlock maybe) */
实际问题:
我们可以使用一个条件变量来同步两个或多个线程吗?如果是怎么办?
如果没有,我该如何解决这个问题?
这里是function(n)
的定义
void *function1 ()
{
while (1)
{
if (count == 4)
{
pthread_mutex_lock (&mutex);
printf("Function 1\n");
count --;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function2 ()
{
while (1)
{
if (count == 3)
{
pthread_mutex_lock (&mutex);
printf("Function 2\n");
count--;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function3 ()
{
while (1)
{
if(count == 2)
{
pthread_mutex_lock (&mutex);
printf("Function 3\n");
count--;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function4 ()
{
while (1)
{
if(count == 1)
{
pthread_mutex_lock (&mutex);
printf("Function 4\n");
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
所需的更改很简单:
而不是:
else
pthread_cond_wait(&cond, &mutex);
这样做:
else {
pthread_mutex_lock (&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);
}
这些更改对我有用,但如果没有更改,会导致不可预测的行为。
编辑:
上面提到的这种简单方法仍然存在竞争条件,并且没有解决 signal
与 broadcast
的问题。为避免这种情况,代码的结构应如下所示:
pthread_mutex_lock (&mutex);
if (count == 4)
{
printf("Function 1\n");
count --;
pthread_mutex_unlock (&mutex);
pthread_cond_broadcast (&cond); // NOTE: broadcast, not signal!
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);
请注意,pthread_cond_broadcast
是必需的,因为您想要唤醒所有线程。
经过更清晰的了解,我已经解决了这个问题。
这是竞争条件的情况。
代码有问题:
使用pthread_cond_broadcast
代替pthread_cond_signal
。
来自 man
页
The pthread_cond_broadcast()
function shall unblock all threads currently blocked on the specified condition variable cond.
The pthread_cond_signal()
function shall unblock at least one of the threads that are blocked on the specified condition variable cond
在检查 if (count == X)
之前未获取 lock
,需要一个
在此之前放置一个锁(因为 count
是 global/shared 变量)。
如果控件转到 else
,则不放置 unlock
。自从一把锁
已经放置(早于 else
),您需要 unlock
它。
如果你不这样做,其他线程将尝试lock
一个互斥量,
那已经被锁定,导致竞争条件。
函数应该如下
void *function1 ()
{
while (1)
{
/* Take a lock on the Mutex */
pthread_mutex_lock (&mutex);
if (4 == count)
{
printf("Function 1\n"); /* Perform your task */
count--;
/* Once operation on shared variable (count) is completed, release lock*/
pthread_mutex_unlock (&mutex);
/* Broadcast to other threads about completion of task */
pthread_cond_broadcast (&cond);
return NULL;
}
else
{
/* If count doesnt match, wait on the condition (wait for signal from other threads) */
pthread_cond_wait(&cond, &mutex);
/* Unlock the mutex, since it was locked earlier - else goes to deadlock */
pthread_mutex_unlock (&mutex);
}
}
return NULL;
}
Here 是完整的工作代码。
我正在尝试创建四个线程来打印一些消息。
我在同步方面遇到了一些问题。
这是我的 main()
的样子
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int count = 4;
int main (void)
{
pthread_t thread1, thread2, thread3, thread4;
pthread_create (&thread4, NULL, function4, NULL);
pthread_create (&thread3, NULL, function3, NULL);
pthread_create (&thread2, NULL, function2, NULL);
pthread_create (&thread1, NULL, function1, NULL);
pthread_join (thread1, NULL);
pthread_join (thread2, NULL);
pthread_join (thread3, NULL);
pthread_join (thread4, NULL);
return 0;
}
function1()
打印 Function 1
,function2()
打印 Function 2
等等。
所需的输出应如下所示:
Function 1
Function 2
Function 3
Function 4
实际输出:
Function 1
/* Infinitely runs (Deadlock maybe) */
实际问题:
我们可以使用一个条件变量来同步两个或多个线程吗?如果是怎么办?
如果没有,我该如何解决这个问题?
这里是function(n)
void *function1 ()
{
while (1)
{
if (count == 4)
{
pthread_mutex_lock (&mutex);
printf("Function 1\n");
count --;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function2 ()
{
while (1)
{
if (count == 3)
{
pthread_mutex_lock (&mutex);
printf("Function 2\n");
count--;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function3 ()
{
while (1)
{
if(count == 2)
{
pthread_mutex_lock (&mutex);
printf("Function 3\n");
count--;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function4 ()
{
while (1)
{
if(count == 1)
{
pthread_mutex_lock (&mutex);
printf("Function 4\n");
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
所需的更改很简单:
而不是:
else
pthread_cond_wait(&cond, &mutex);
这样做:
else {
pthread_mutex_lock (&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);
}
这些更改对我有用,但如果没有更改,会导致不可预测的行为。
编辑:
上面提到的这种简单方法仍然存在竞争条件,并且没有解决 signal
与 broadcast
的问题。为避免这种情况,代码的结构应如下所示:
pthread_mutex_lock (&mutex);
if (count == 4)
{
printf("Function 1\n");
count --;
pthread_mutex_unlock (&mutex);
pthread_cond_broadcast (&cond); // NOTE: broadcast, not signal!
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);
请注意,pthread_cond_broadcast
是必需的,因为您想要唤醒所有线程。
经过更清晰的了解,我已经解决了这个问题。
这是竞争条件的情况。
代码有问题:
使用
pthread_cond_broadcast
代替pthread_cond_signal
。
来自man
页The
pthread_cond_broadcast()
function shall unblock all threads currently blocked on the specified condition variable cond.The
pthread_cond_signal()
function shall unblock at least one of the threads that are blocked on the specified condition variable cond在检查
if (count == X)
之前未获取lock
,需要一个 在此之前放置一个锁(因为count
是 global/shared 变量)。如果控件转到
else
,则不放置unlock
。自从一把锁 已经放置(早于else
),您需要unlock
它。如果你不这样做,其他线程将尝试
lock
一个互斥量, 那已经被锁定,导致竞争条件。
函数应该如下
void *function1 ()
{
while (1)
{
/* Take a lock on the Mutex */
pthread_mutex_lock (&mutex);
if (4 == count)
{
printf("Function 1\n"); /* Perform your task */
count--;
/* Once operation on shared variable (count) is completed, release lock*/
pthread_mutex_unlock (&mutex);
/* Broadcast to other threads about completion of task */
pthread_cond_broadcast (&cond);
return NULL;
}
else
{
/* If count doesnt match, wait on the condition (wait for signal from other threads) */
pthread_cond_wait(&cond, &mutex);
/* Unlock the mutex, since it was locked earlier - else goes to deadlock */
pthread_mutex_unlock (&mutex);
}
}
return NULL;
}
Here 是完整的工作代码。