在wait()/ signal()块中获取互斥锁会发生什么?

时间:2016-12-26 10:47:05

标签: multithreading operating-system synchronization mutex semaphore

所以练习的描述:
你有这个餐厅,其中有N个点,你可以要求一部分薯条。每个点都有M个部分。有1个frycheff。当订单点有2个部分时,它会警告cheff它需要重新填充。 cheff按FIFO的顺序传送部分。 我们制作了这个伪代码:

      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)函数重新调用,但是以重置方式调用,以便函数以新的形式运行? 提前致谢!

1 个答案:

答案 0 :(得分:1)

spring.redis.pool.max-active spring.redis.pool.max-idle spring.redis.pool.max-wait spring.redis.pool.min-idle 的手册页提供了有关该行为的更多信息。它具体讨论了pthread的实现,但这适用于一般的每个实现 https://linux.die.net/man/3/pthread_cond_wait

最重要的部分是:

  

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

wait()是一个阻止通话。线程由调度程序进入休眠状态。收到信号后,wait()将返回。没有跳跃。执行将在wait()之后继续执行。

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

wait()
  

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

调用// Condition: portions[n] > 0 while(portions[n] == 0) cond_point[n].wait(mutex[n]); 时,需要锁定互斥锁。

  

成功返回后,互斥锁应被锁定,并由调用线程拥有。

wait()返回时,它将重新获得锁定。正如你所看到的,任何其他事情都没有意义,并且会导致令人困惑的情况。

所以这将是(可能)发生的事情:

wait()

顺便说一下:您应该使用另一个互斥锁将frycheff的调用同步到--- 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()) if(!waitline.empty()),因为ArrayList上的写操作不是threadsave。