2015-01-12 101 views
1

我被prof.Remzi http://pages.cs.wisc.edu/~remzi/OSTEP/唤醒/等待比赛锁定?

通过OSTEP读书,我只能部分地理解如何在唤醒/下面的代码结果等待比赛的状态。(代码是从书章采取。 http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf

void lock(lock_t *m) { 
    while (TestAndSet(&m->guard, 1) == 1); //acquire guard lock by spinning 
     if (m->flag == 0) { 
      m->flag = 1; // lock is acquired 
      m->guard = 0; 
     } else { 
      queue_add(m->q, gettid()); 
      m->guard = 0; 
      park(); 
     } 
    } 
} 

void unlock(lock_t *m) { 
    while (TestAndSet(&m->guard, 1) == 1); //acquire guard lock by spinning 
     if (queue_empty(m->q)) 
      m->flag = 0; // let go of lock; no one wants it 
     else 
      unpark(queue_remove(m->q)); // hold lock (for next thread!) 
     m->guard = 0; 
} 

公园()调用SYS使调用线程睡觉,和取消驻留(线程ID)来唤醒由线程ID指定一个特定的线程。

现在,如果线程1通过设置日持有锁e m->标志为1.如果线程2进入获取锁定,则失败。因此else case被执行,并且thread2被添加到队列中,但是 - 假定 -f在park()sys调用之前,thread2被调度并且thread1被赋予时间片。如果thread1释放锁,则解锁函数会尝试调用unpark syscall(队列非空),因为thread2在队列中。但是thread2没有调用park()sys调用,它只是被添加到队列中。

所以问题
1)什么是线程1的取消搁置()返回时,只是一个错误说线程ID没有发现?(OS特定)
2)会发生什么变化锁标志?它应该在调用锁定例程的后续线程之间传递,只有在没有更多锁定争用时才释放锁定。

本书说thread2将永远睡眠。但我的理解是任何随后的线程争夺锁将永远睡觉,说thread3试图在稍后获取锁,因为锁在解锁调用期间永远不会被thread1释放。

我的理解很可能是错误的,因为这本书是非常具体的指出thread2永远睡觉。或者我只是在例子中阅读太多,我的理解是正确的?有一个僵局?

回答

0

将此问题邮寄给了Prof.Remzi教授,并得到了他的回复!!!在这里发布回复。

Prof.Remzi的答复:

好问题!

我认为你基本上没错。

unpark()将返回(也许说,threadID没有睡觉); 在这个实现中,锁被锁定,并且thread2将永远睡眠,并且如您所说的所有后续线程试图获取锁将不会是 能够。