【问题标题】:How does Monitor Synchronisation work?监视器同步如何工作?
【发布时间】:2013-04-10 21:29:31
【问题描述】:

所以我正在阅读有关同步的内容,并且遇到过监视器,但似乎无法理解它们是如何工作的。

我看到一般布局是以下格式的东西,我可以看到 条件变量(我不太确定这些是做什么的):

monitor {
    // shared variables
    procedure P1 (..) {..}
    ...
    procedure P2 (..) {..}
    initialisation code (..) {..}
}

但是,尽管我对此一头雾水,但我无法真正看到如何像所描述的那样的监视器一次只允许一个进程访问。 p>

【问题讨论】:

    标签: multithreading process synchronization semaphore monitor


    【解决方案1】:

    我喜欢将监视器视为具有私有互斥锁的对象,并且每个过程都受到该互斥锁的保护。所以像:

    MyClass {
      // private shared variables
      ...
      mutex m;
      // public procedures
      Procedure P1(...) {
        acquire(m);
        ...
        release(m);
      }
      Procedure P2(...) {
        acquire(m);
        ...
        release(m);
      }
      initialisation code (...) { ... }
    }
    

    互斥锁保证一次只有一个线程/进程可以操作对象,因为每个公共过程都被互斥锁获取/释放包装。

    现在那些条件变量呢?嗯,通常你不需要它们。但有时你会遇到一个线程需要等待另一个线程的情况,这就是条件变量的用武之地。

    例如,假设您正在实现一个并发队列对象。您将有一个push() 过程和一个pop() 过程。但是如果队列是空的怎么办?

    因为这样的代码,单独的 empty() 和 pop() 过程是行不通的:

    Thread A                Thread B
    if (not q.empty())
                            if (not q.empty())
                            then q.pop() // now q is empty!
    then q.pop() // error!
    

    因此,您必须定义一个 pop() 过程,该过程在队列为空时返回一个特殊值,然后旋转等待队列变为非空。但是旋转等待的效率非常低。

    所以改为使用条件变量。条件变量有两种方法:wait()notify()。 Wait() 原子地放弃你持有的互斥锁,然后阻塞线程,直到其他线程调用 notify()。像这样:

    condition_variable cv;
    Procedure int pop() {
      acquire(m);
      while (q.empty()) {
        wait(cv, m)  // atomically release m and wait for a notify() on cv.
        // when wait() returns it automatically reacquires mutex m for us.
      }
      rval = q.pop();
      release(m);
      return rval;
    }
    Procedure push(int x) {
      acquire(m);
      q.push(x);
      notify(cv);  // wake up everyone waiting on cv
      release(m);
    }
    

    现在您有了一个数据结构/对象,其中一次只能有一个线程访问该对象,并且您可以处理不同线程之间的操作需要以特定顺序发生的情况(例如至少一个push() 必须在每个 pop() 完成之前发生。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-29
      • 2019-09-14
      • 2019-05-20
      • 1970-01-01
      相关资源
      最近更新 更多