锁和条件变量

一直对于条件变量的原理不是特别清楚,今天google了下,搜到了斯坦福大学os的课件,算是看明白了。

Locks

  • 锁:在任意时间一个对象只能被一个线程拥有。锁有以下基础操作:
    • acquire:使得锁被当前线程拥有;如果其他线程已经拥有锁,要等待这个锁被释放。锁特别包含一个等待线程队列信息的堆栈。
    • release:释放锁(必须被持有的当前线程释放)
  • 比如
    struct lock l;
    ...
    lock_acquire(&l);
    if (milk == 0) {
      buy_milk();
    }
    lock_release(&l);
  • 更复杂的例子是生产者消费者:
    • 生产者向buffer加字幕
    • 消费者从buffer移除字母
    • 字母将被以放入的顺序被移除
    • 比如:
      char buffer[SIZE];
      int count = 0, putIndex = 0, getIndex = 0;
      struct lock l;
      lock_init(&l);
      
      void put(char c) {
          lock_acquire(&l);
          count++;
          buffer[putIndex] = c;
          putIndex++;
          if (putIndex == SIZE) {
              putIndex = 0;
          }
          lock_release(&l);
      }
      
      char get() {
          char c;
          lock_acquire(&l);
          count--;
          c = buffer[getIndex];
          getIndex++;
          if (getIndex == SIZE) {
              getIndex = 0;
          }
          lock_release(&l);
          return c;
      }
      
    • Version 2 (handle empty/full cases):
      char buffer[SIZE];
      int count = 0, putIndex = 0, getIndex = 0;
      struct lock l;
      lock_init(&l);
      
      void put(char c) {
          lock_acquire(&l);
          while (count == SIZE) {
              lock_release(&l);
              lock_acquire(&l);
          }
          count++;
          buffer[putIndex] = c;
          putIndex++;
          if (putIndex == SIZE) {
              putIndex = 0;
          }
          lock_release(&l);
      }
      
      char get() {
          char c;
          lock_acquire(&l);
          while (count == 0) {
              lock_release(&l);
              lock_acquire(&l);
          }
          count--;
          c = buffer[getIndex];
          getIndex++;
          if (getIndex == SIZE) {
              getIndex = 0;
          }
          lock_release(&l);
          return c;
      }
      

条件变量:

  • 同步机制需要的不止是互相掣肘;也需要一种方式去等待另外一线程做一些事情(比如 等待一个字母加进buffer)
  • Condition variables: used to wait for a particular condition to become true (e.g. characters in buffer).
  • 条件变量:用来等待一个特定的条件变为true。
    • wait(condition, lock): 释放锁,休眠当前线程知道条件符合被唤醒;当线程被唤醒,再次获得锁。
    • signal(condition, lock): i如果有任何线程在等待这个条件变量,唤醒其中一个。调用者必须持有锁,而且必须与等待条件使用的是同一把锁。
    • broadcast(condition, lock): 与信号一样,当然是唤醒所有等待线程。
    • Note: after signal, signaling thread keeps lock, waking thread goes on the queue waiting for the lock.
    • 注意:signal后,signaling线程继续持有锁,唤醒线程继续等待在锁上。
    • 注意:当一个线程被条件唤醒并不保证条件符合。
  • Producer/Consumer, version 3 (with condition variables):
    char buffer[SIZE];
    int count = 0, putIndex = 0, getIndex = 0;
    struct lock l;
    struct condition dataAvailable;
    struct condition spaceAvailable;
    
    lock_init(&l);
    cond_init(&dataAvailable);
    cond_init(&spaceAvailable);
    
    void put(char c) {
        lock_acquire(&l);
        while (count == SIZE) {
            cond_wait(&spaceAvailable, &l);
        }
        count++;
        buffer[putIndex] = c;
        putIndex++;
        if (putIndex == SIZE) {
            putIndex = 0;
        }
        cond_signal(&dataAvailable, &l);
        lock_release(&l);
    }
    
    char get() {
        char c;
        lock_acquire(&l);
        while (count == 0) {
            cond_wait(&dataAvailable, &l);
        }
        count--;
        c = buffer[getIndex];
        getIndex++;
        if (getIndex == SIZE) {
            getIndex = 0;
        }
        cond_signal(&spaceAvailable, &l);
        lock_release(&l);
        return c;
    }
    

Monitors

  • 当锁和条件变量一起用,结果被叫做监察者
    • A collection of procedures manipulating a shared data structure.
    • One lock that must be held whenever accessing the shared data (typically each procedure acquires the lock at the very beginning and releases the lock before returning).
    • One or more condition variables used for waiting.
  • There are other synchronization mechanisms besides locks and condition variables. Be sure to read about semaphores in the book or in the Pintos documentation.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值