5

问题:在多线程程序中,是否可以保证代码一次只能在一个线程中执行?(或近似于此的东西)

具体来说:我有一个控制器 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都将继续。此 hack 确保 A 在 M 可以再次锁定互斥锁之前不会解锁互斥锁,从而允许 A 第二次重新获得锁并再次运行(它应该只运行一次)。

do-while 似乎有点矫枉过正,但确实有效。所以我的问题是,有没有更好的方法?

4

3 回答 3

2

假设您在 Windows 上运行,您可能会尝试查看 Fibers。(参见例如http://developer.amd.com/Pages/1031200677.aspx或只是谷歌“windows fiber”。)

我怀疑你真的在寻找协程。

于 2012-05-05T13:54:57.243 回答
1

检查 Win32 中的“CriticalSection”。C++ 11 使用了另一个术语“lock_guard”。

如何使用 Boost 制作关键部分?

http://en.cppreference.com/w/cpp/thread/lock_guard

你的代码

do{}while(lockval==0);

会吃掉你的CPU性能。

于 2012-05-05T13:40:10.713 回答
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;
}
于 2012-05-06T01:26:58.533 回答