简体   繁体   English

同步线程,互斥

[英]Synchronizing threads, mutex

I'm trying to do my homework but I'm stuck with these threads.. This function is called when a thread is created: 我正在尝试做我的作业,但我被这些线程困住了。创建线程时将调用此函数:

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);
}

My problem is that when I have 5 mines and 2 workers, only one worker gets in the mine and digs the gold. 我的问题是,当我有5个矿山和2个工人时,只有一个工人进入矿山并挖金。 How can I rotate my threads so all of them can dig from the mine? 我该如何旋转线程,以便所有线程都可以从矿井中挖出?

If you want 1 miner per mine, but you have more miners than mines, then you have to decide what the idle miners will do when all the mines are in use. 如果每个矿井要1个矿工,但矿井比矿井多,则必须决定在使用所有矿井时空闲的矿工将做什么。 Furthermore, if you have a mutex per mine, and everyone tries to take the first mutex, only one miner will win, and the others will still block. 此外,如果每个地雷都有一个互斥量,并且每个人都尝试使用第一个互斥量,则只有一个矿工会获胜,而其他矿工仍会阻止。 You can use a try lock, but then the miners will busy wait when all the mines are full. 您可以使用尝试锁,但是当所有地雷都装满时,矿工将忙于等待。

You could use a semaphore that is initialized with the number of mines. 您可以使用以地雷数量初始化的信号量。 Each miner, upon successfully acquiring the semaphore would know that there is a mine available for them, but they wouldn't know which one. 每个矿工一旦成功获取了信号量,便会知道有一个地雷可供他们使用,但他们不知道哪一个。 You could use a single mutex to protect all of the mines' in-use state. 您可以使用单个互斥锁来保护所有地雷的使用状态。 After acquiring the semaphore, you then acquire the mutex, hunt for an available mine, mark it as in-use, release the mutex and start mining. 获取信号量之后,您便需要获取互斥锁,寻找可用的地雷,将其标记为使用中,释放互斥锁并开始挖掘。 Then, when you are done, re-acquire the mutex, mark the mine as available, release the mutex, and then release the semaphore. 然后,完成操作后,重新获取互斥锁,将地雷标记为可用,释放互斥锁,然后释放信号灯。

Finally, instead of the semaphore, you could use a condition variable and a mutex. 最后,您可以使用条件变量和互斥锁来代替信号灯。 Acquire the mutex, and hunt for an available mine. 获取互斥量,并寻找可用的地雷。 If you cannot find one, block on the condvar. 如果找不到,请在condvar上阻止。 If you do find one, mark it as in use, release the mutex, and start mining. 如果找到一个,将其标记为已使用,释放互斥锁,然后开始挖掘。 When you are done, re-acquire the mutex, mark the mine as available, signal the condvar, and release the mutex. 完成后,重新获取互斥锁,将地雷标记为可用,向condvar发出信号,然后释放互斥锁。 A thread that awakes on the condvar will have automatically re-acquired the mutex and should loop around and re-hunt for an available mine. 在condvar上唤醒的线程将自动重新获取互斥锁,并且应该循环并重新寻找可用的地雷。 In this case, it should be sufficient to signal the condvar instead of broadcasting; 在这种情况下,用信号通知condvar而不是广播就足够了; although broadcasting can be safer. 尽管广播可能更安全。

Also, once you have parallel miners, you're going to have to rethink the global gold and gold_collected. 此外,一旦有了并行的矿工,就必须重新考虑全球的gold和gold_collected。 Since your miners will be doing the actual mining without holding a mutex, they cannot update these globals while mining. 由于您的矿工将在不持有互斥锁的情况下进行实际采矿,因此他们无法在采矿时更新这些全局变量。 They should keep a local tally of the amount of gold they mined, and update the global once the mutex has been re-acquired. 他们应保持所开采黄金量的本地统计,并在重新获得互斥量后更新全局数据。 Maybe gold can be deducted before the miner enters the mine, and gold_collected updated after leaving the mine (both while holding the mutex). 也许可以在矿工进入矿山之前扣除金,并在离开矿场之后(同时持有互斥锁)更新gold_collected。 It's also a little iffy reading gold when not holding the mutex, since it could change underneath you... 当不持有互斥锁时,读黄金也有点不愉快,因为它可能会在您下面改变。

There is only one mutex for both mines, so only one worker can be working in the mines. 两个矿井只有一个互斥锁,因此只有一名工人可以在矿井中工作。 If you have one mutex per mine, then two workers can enter in mines at same time (one worker in each mine). 如果每个矿井有一个互斥锁,则两名工人可以同时进入矿井(每个矿井中有一名工人)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM