如何序列化异步 pthreads 代码段
How to serialize async pthreads code sections
我有许多想要临时访问共享资源的抢占式(异步)线程 (TA)。这将是 pthread_mutex
.
的典型用法
但是,我有一些事情让事情变得更复杂:
我无法控制完整的代码,因为我只提供了一组函数来简化该过程。
有一组 "main" 线程 (TM),我几乎无法控制它们,它们使用私有互斥体来访问所述共享资源。他们使用管理这些线程的私有调度程序,以这样一种方式,任何时候都只允许一个 运行,有效地让这些线程 运行 协作。
这些主线程 (TM) 中的任何一个都可能导致异步线程 (TA) 运行。这就是我要为其提供额外功能的程序员代码的全部部分。
我必须等待那些 TM 线程处于 "safe" 状态,然后我才能允许 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()
。我做错了什么?
当dispatch_semaphore_signal() returns 0(表示没有人等待)时,它已经增加了信号量,因此下一个dispatch_semaphore_wait()将获得信号量无需等待。
你要的是条件变量,dispatch没有提供。可以使用信号量[即。保留一个单独的柜台
有多少人被互斥体保护唤醒]],但在这一点上你可能想考虑一下你是否没有挖一个更深的洞。
Dispatch 在设计时考虑了特定的模型,而您似乎正在努力颠覆它。有没有办法以其他方式获得您想要的效果?
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);
}
我有许多想要临时访问共享资源的抢占式(异步)线程 (TA)。这将是 pthread_mutex
.
但是,我有一些事情让事情变得更复杂:
我无法控制完整的代码,因为我只提供了一组函数来简化该过程。
有一组 "main" 线程 (TM),我几乎无法控制它们,它们使用私有互斥体来访问所述共享资源。他们使用管理这些线程的私有调度程序,以这样一种方式,任何时候都只允许一个 运行,有效地让这些线程 运行 协作。
这些主线程 (TM) 中的任何一个都可能导致异步线程 (TA) 运行。这就是我要为其提供额外功能的程序员代码的全部部分。
我必须等待那些 TM 线程处于 "safe" 状态,然后我才能允许 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()
。我做错了什么?
当dispatch_semaphore_signal() returns 0(表示没有人等待)时,它已经增加了信号量,因此下一个dispatch_semaphore_wait()将获得信号量无需等待。
你要的是条件变量,dispatch没有提供。可以使用信号量[即。保留一个单独的柜台 有多少人被互斥体保护唤醒]],但在这一点上你可能想考虑一下你是否没有挖一个更深的洞。
Dispatch 在设计时考虑了特定的模型,而您似乎正在努力颠覆它。有没有办法以其他方式获得您想要的效果?
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);
}