如何序列化异步pthreads代码段
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何序列化异步pthreads代码段相关的知识,希望对你有一定的参考价值。
我有许多需要临时访问共享资源的抢先(异步)线程(TA)。这将是pthread_mutex
的典型用途。
但是,我有一些事情使这更复杂:
- 我几乎无法控制整个代码,因为我只提供了一组函数来简化程序。
- 有一组“主”线程(TM),我几乎无法控制,并使用私有互斥锁来访问所述共享资源。他们使用管理这些线程的私有调度程序,这样只允许一个人在任何时间运行,有效地让这些线程协同运行。
- 任何这些主线程(TM)都可能导致异步线程(TA)运行。这是我想要提供额外功能的程序员代码的所有部分。
我必须等待那些TM线程处于“安全”状态,然后我可以允许TA线程访问共享资源。我有办法做到这一点。
因此,想法是暂停(阻止)所有TA线程,直到在任何一个TM线程中达到安全状态,然后暂停该TM线程,允许每个TA线程一个接一个地运行,并恢复TM线程一旦完成它们。
当TM线程达到所述安全状态时,将调用我的函数shared_resource_is_safe()
。
此外,程序员必须在访问共享资源之前和之后调用我的函数acquire_access()
和surrender_access()
。
所以我有三个功能要实现,我正在努力使用互斥锁和/或信号量来实现我的目标。
这是我到目前为止所提出的:
dispatch_semaphore_t semaphore;
pthread_mutex_t mutex;
int is_safe = 0;
void setup_once() {
semaphore = dispatch_semaphore_create (0);
pthread_mutex_init (&mutex, NULL);
}
void acquire_access() {
pthread_mutex_lock (&mutex);
dispatch_semaphore_wait (semaphore, DISPATCH_TIME_FOREVER);
assert(is_safe);
}
void surrender_access() {
pthread_mutex_unlock (&mutex);
}
void shared_resource_is_safe() {
// this shall resume thread that's called acquire_access()
is_safe = 1;
while (dispatch_semaphore_signal (semaphore) != 0) {
// Wait until the signaled thread
// has called surrender_access()
pthread_mutex_lock (&mutex);
pthread_mutex_unlock (&mutex);
}
is_safe = 0;
}
信号量用于任何线程调用acquire_access()
等待shared_resource_is_safe()
。
互斥锁应确保每个异步线程都等待shared_resource_is_safe()
允许它运行。
但这并不能可靠地工作。我遇到了is_safe
的断言在异步线程中失败的情况,这意味着主线程不会等待异步线程调用surrender_access()
。我做错了什么?
mevets的答案可以识别你的错误。如上所述,您可以使用条件变量来解决此问题:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_safe = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_waiters = PTHREAD_COND_INITIALIZER;
int is_safe = 0;
long waiters = 0;
void acquire_access(void)
{
pthread_mutex_lock(&mutex);
waiters++;
while (!is_safe)
pthread_cond_wait(&cond_safe, &mutex);
}
void surrender_access(void)
{
waiters--;
if (!waiters)
pthread_cond_signal(&cond_waiters);
pthread_mutex_unlock(&mutex);
}
void shared_resource_is_safe(void)
{
pthread_mutex_lock(&mutex);
if (waiters)
{
is_safe = 1;
pthread_cond_broadcast(&cond_safe);
while (waiters)
pthread_cond_wait(&cond_waiters, &mutex);
is_safe = 0;
}
pthread_mutex_unlock(&mutex);
}
当dispatch_semaphore_signal()返回0(表示没有人等待它)时,它增加了信号量,因此下一个dispatch_semaphore_wait()将获取信号量而不等待。
你想要的是一个条件变量,调度不提供。可以使用信号量构造一个[即。保持一个单独的计数器,表示有多少人被互斥锁保护起来,但是在这一点上,你可能想要考虑一下你是不是要挖一个更深的洞。
Dispatch的设计考虑了特定的模型,你似乎正在努力颠覆它。有没有办法以另一种方式获得你想要的效果?
以上是关于如何序列化异步pthreads代码段的主要内容,如果未能解决你的问题,请参考以下文章