问题:是否可以保证代码执行只能在多线程程序中一次发生在一个线程中? (或者近似于此的东西)
具体来说:我有一个控制器M(这是一个线程)和线程A,B,C。我希望M能够决定谁应该被允许运行。当线程完成时(最终或暂时),控件将转回M。
为什么:理想情况下,我希望A,B和C在自己的线程中执行其代码而其他线程未运行。这将使每个线程在它们暂停时保持其指令指针和堆栈,当控制器将控制权交还给它们时,从它们停止的位置开始。
我现在在做什么:我已经编写了一些实际上可以执行此操作的代码 - 但我不喜欢它。
在伪C中:
//Controller M
//do some stuff
UnlockMutex(mutex);
do{}while(lockval==0);
LockMutex(mutex);
//continue with other stuff
//Thread A
//The controller currently has the mutex - will release it at UnlockMutex
LockMutex(mutex);
lockval=1;
//do stuff
UnlockMutex(mutex);
原因
do{}while(lockval==0);
是必需的,当互斥锁解锁时,A和M都将继续。此黑客确保A在M再次锁定之前不会解锁互斥锁,从而允许A再次重新锁定并再次运行(它应该只运行一次)。
这种做法看起来有点矫枉过正,但确实有效。所以我的问题是,有更好的方法吗?
答案 0 :(得分:2)
假设您在Windows上运行,您可能会尝试查看Fibers。 (参见例如http://developer.amd.com/Pages/1031200677.aspx或仅谷歌“windows fiber”。)
我怀疑你真的在寻找协程。
答案 1 :(得分:1)
在Win32中检查“CriticalSection”。 C ++ 11使用另一个术语“lock_guard”。
How do I make a critical section with Boost?
http://en.cppreference.com/w/cpp/thread/lock_guard
您的代码
do{}while(lockval==0);
会耗尽你的CPU性能。
答案 2 :(得分:0)
我认为你在linux下编写c ++并使用pthread API。 这是代码,不是那么强大,而是一个很好的起点。希望对你有用。 使用“g ++ test_controller_thread.cpp -pthread -o test_controller_thread”来创建二进制执行程序。
// 3 threads, one for controller, the other two for worker1 and worker2.
// Only one thread can proceed at any time.
// We use one pthread_mutex_t and two pthread_cond_t to guarantee this.
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_controller_cond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t g_worker_cond = PTHREAD_COND_INITIALIZER;
void* controller_func(void *arg) {
printf("entering the controller thread. \n");
// limit the max time the controller can run
int max_run_time = 5;
int run_time = 0;
pthread_mutex_lock(&g_mutex);
while (run_time++ < max_run_time) {
printf("controller is waitting.\n");
pthread_cond_wait(&g_controller_cond, &g_mutex);
printf("controller is woken up.\n");
pthread_cond_signal(&g_worker_cond);
printf("signal worker to wake up.\n");
}
pthread_mutex_unlock(&g_mutex);
}
void* worker_func(void *arg) {
int work_id = *(int*)arg;
printf("worker %d start.\n", work_id);
pthread_mutex_lock(&g_mutex);
while (1) {
printf("worker %d is waitting for controller.\n", work_id);
pthread_cond_wait(&g_worker_cond, &g_mutex);
printf("worker %d is working.\n", work_id);
pthread_cond_signal(&g_controller_cond);
printf("worker %d signal the controller.\n", work_id);
}
pthread_mutex_unlock(&g_mutex);
}
int main() {
pthread_t controller_thread, worker_thread_1, worker_thread_2;
int worker_id_1 = 1;
int worker_id_2 = 2;
pthread_create(&controller_thread, NULL, controller_func, NULL);
pthread_create(&worker_thread_1, NULL, worker_func, &worker_id_1);
pthread_create(&worker_thread_2, NULL, worker_func, &worker_id_2);
sleep(1);
printf("\nsignal the controller to start all the process.\n\n");
pthread_cond_signal(&g_controller_cond);
pthread_join(controller_thread, NULL);
pthread_cancel(worker_thread_1);
pthread_cancel(worker_thread_2);
return 0;
}