同步线程,互斥

时间:2014-03-25 01:00:26

标签: c multithreading synchronization mutex sync

我正在尝试做我的作业,但我坚持使用这些线程..在创建一个线程时调用此函数:

size_t* mines, gold = 0, gold_collected = 0;
pthread_mutex_t mine_mutex;
int last_mine = 0;

void* dig(void *mine_start) {
        int current_worker = (int)mine_start;
        int mine = (int)mine_start;

//      printf("Hello, it's me, thread %d\n", current_worker);

        while(gold != 0) {
                if(mine > last_mine - 1) {
                        mine = 0;
                }
                pthread_mutex_lock(&mine_mutex);
                if(mines[mine] != 0) {
                        //printf("All gold %zd\n", gold);
                        //printf("Gold in mine %zd with number %d\n", mines[mine], mine);
                        printf("Worker %d entered mine %d\n", current_worker, mine);
                        gold -= 10;
                        mines[mine] -= 10;
                        gold_collected += 10;
                        //sleep(1);    
                }
                pthread_mutex_unlock(&mine_mutex);
                ++mine;
        }
        pthread_exit(NULL);
}

我的问题是,当我有5个地雷和2个工人时,只有一个工人进入矿井并挖掘金矿。如何旋转我的线程以便所有人都可以从我的线上挖掘?

2 个答案:

答案 0 :(得分:1)

如果你想要每个矿井1个矿工,但你拥有的矿工多于矿工,那么你必须决定当所有矿井都在使用时,闲置的矿工会做些什么。此外,如果你的每个矿井都有一个互斥锁,并且每个人都试图使用第一个互斥锁,那么只有一个矿工会获胜,而其他矿工仍会阻止。您可以使用试锁,但是当所有地雷都已满时,矿工将忙着等待。

您可以使用使用地雷数量初始化的信号量。每个矿工在成功获得信号量后都知道有一个可用的矿井,但他们不知道哪一个。您可以使用单个互斥锁来保护所有地雷的使用状态。获取信号量后,您获取互斥锁,寻找可用的矿山,将其标记为正在使用,释放互斥锁并开始挖掘。然后,完成后,重新获取互斥锁,将矿标记为可用,释放互斥锁,然后释放信号量。

最后,您可以使用条件变量和互斥量来代替信号量。获取互斥锁,并寻找可用的矿井。如果你找不到一个,就在condvar上阻止。如果找到一个,请将其标记为正在使用,释放互斥锁,然后开始挖掘。完成后,重新获取互斥锁,将矿井标记为可用,发出condvar信号,然后释放互斥锁。在condvar上唤醒的线程将自动重新获取互斥锁,并且应该循环并重新寻找可用的矿井。在这种情况下,应该足以发出condvar信号而不是广播;虽然广播可以更安全。

此外,一旦你有平行的矿工,你将不得不重新考虑全球黄金和黄金收集。由于您的矿工将在不持有互斥锁的情况下进行实际挖掘,因此他们无法在挖掘时更新这些全局变量。他们应该保留他们开采的黄金量的当地记录,并在重新获得互斥量后更新全局。也许在矿工进入矿井之前可以扣除黄金,并且在离开矿山之后更新gold_collected(同时持有互斥锁)。如果没有持有互斥锁,它也会有点不确定,因为它可能会在你的下方发生变化......

答案 1 :(得分:0)

两个地雷只有一个互斥锁,因此只有一个工人可以在矿井中工作。如果每个矿井有一个互斥锁,那么两个工人可以同时进入矿井(每个矿井中有一个工人)。