What happens to mutex acquirement in wait()/signal() block?

被刻印的时光 ゝ 提交于 2019-12-25 18:42:26

问题


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

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!


回答1:


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

The most important parts are these:


pthread_cond_wait() functions shall block on a condition variable

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().

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.

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.

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: 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.



来源:https://stackoverflow.com/questions/41330061/what-happens-to-mutex-acquirement-in-wait-signal-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!