在wait()/signal()块中获取互斥锁会怎样? [英] What happens to mutex acquirement in wait()/signal() block?

查看:151
本文介绍了在wait()/signal()块中获取互斥锁会怎样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,练习的描述是:
您在这家餐厅里有N分,您可以在那里索要一份炸薯条.每个点有M个部分.这里有1个frycheff.当订购点有2份时,它会警告厨师需要重新装填. Cheff按FIFO的顺序交付这些部分. 我们做了这个伪代码:

So the description of the exercise:
You have this restaurant in which there are N points where you can ask for a portion of fries. Each point has M portions. There is 1 frycheff. When an order-point has 2 portions, it warns the cheff that it needs a refill. The cheff delivers the portions in order of FIFO. We made this pseudo-code:

      init {
    Semafoor[] mutex;
    Condition[] cond_point = new Condition[N];
    int[] portions = new int[N];
    ArrayList<int> waitline = new ArrayList<int>();

    for(int i = 0; i < N; i++) {
        mutex[i] = new Semafoor(1);
        portions[i] = M;
    }
}

point(int n) {
    while(1) {
        mutex[n].acquire();
        if(portions[n] == 0) {
            cond_point[n].wait(mutex[n]);
        }
        else if(portios[n] == 2) {
            waitline.add(n);
        }
        portions[n]--;
        mutex[n].release();
    }
}

frycheff() {
    int n;
    while(1) {
        if(!waitline.empty()) {
            n = waitline.remove(0);
            mutex[n].acquire();
            portions[n] += M;
            cond_point[n].signal();
            mutex[n].release();
        }
    }
}

所以我们想知道当wait()语句阻塞point(int n)信号时会发生什么.在我们的纪录片中,它说它们以原子方式释放互斥体,因此没有干扰.但是其他代码行呢? (在point(int n)函数中)? portions[n]-等-行是否被丢弃? signal()语句会以重置方式重新调用point(int n)函数,以便该函数作为新函数运行吗? 提前致谢!

So we were wondering what happens when the wait() statement blocks the point(int n) signal. In our documentary it says they release the mutex in an atomic way, so there is no interference. But what about the other lines of code? (in the point(int n) function)? Are the portions[n]-- etc. - lines discarded? Will the signal() statement recall to the point(int n) function but in a reset manner so the function will run as new? Thanks in advance!

推荐答案

wait()的手册页包含有关此行​​为的更多信息.它专门讨论了pthread实现,但这通常适用于每个实现.
https://linux.die.net/man/3/pthread_cond_wait

The man page of wait() has further information about the behaviour. It talks about the pthread implementation specifically but this applies to every implementation in general.
https://linux.die.net/man/3/pthread_cond_wait

最重要的部分是这些:

pthread_cond_wait()函数应在条件变量上阻塞

pthread_cond_wait() functions shall block on a condition variable

wait()是阻止呼叫.线程由调度程序进入睡眠状态.接收到信号后,wait()将返回.没有跳跃.执行将在wait()之后继续.

wait() is a blocking call. The thread is put to sleep by the scheduler. wait() will return when a signal is received. There are no jumps. The execution will continue right after wait().

注意:由于虚假唤醒wait()可能会在没有充分理由的情况下返回.因此,您应该检查条件是否真正满足.循环调用wait():

Note: Because of spurious wakeups it is possible that wait() returns without good reason. You should therefore check if the condition really is met. Call wait() in a loop:

// Condition: portions[n] > 0
while(portions[n] == 0)
    cond_point[n].wait(mutex[n]);


应使用被调用线程锁定的互斥锁或未定义的行为结果来调用它们.

They shall be called with mutex locked by the calling thread or undefined behavior results.

调用wait()时,互斥锁已经需要锁定.

The mutex already needs to be locked when wait() is called.

成功返回后,互斥锁应已被锁定,并应归调用线程所有.

Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.

wait()返回时,它将重新获取锁定.如您所见,其他任何事情都没有意义,并且会导致混乱的情况.

When wait() returns it will have reacquired the lock. Anything else makes no sense and would lead to confusing situations, as you have seen.

这就是(可能)发生的事情:

So this is what will (could) happen:

--- point ------------------------- frycheff -------------------
mutex[n].acquire();                 Serving other Points
else if(portios[n] == 2)            Serving other Points
waitline.add(n);                    Serving other Points
portions[n]--;                      Serving other Points
mutex[n].release();                 Serving other Points
...
mutex[n].acquire(); (BLOCKS)        if(!waitline.empty())
mutex[n].acquire();                 n = waitline.remove(0);
if(portions[n] == 0)                mutex[n].acquire(); (BLOCKS)
cond_point[n].wait(mutex[n]);       mutex[n].acquire();
Sleeping                            portions[n] += M;
Sleeping                            cond_point[n].signal();
wait() reaquires mutex[n]           mutex[n].release();
portions[n]--;                      if(!waitline.empty())
mutex[n].release();                 if(!waitline.empty())

Btw:您可能应该使用另一个互斥锁将frycheff的调用同步到if(!waitline.empty())n = waitline.remove(0);,因为对ArrayList的写操作不是threadave.

Btw: You should probably use another mutex to synchronize the frycheff's calls to if(!waitline.empty()) and n = waitline.remove(0); because write operations on an ArrayList are not threadsave.

这篇关于在wait()/signal()块中获取互斥锁会怎样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆