简体   繁体   English

一个实现信号量的建议,为什么是错误的?

[英]A Suggestion for Implementing Semaphores, Why It's Wrong?

I found this slide in my digital textbook (I tried to copy the text but it won't allow me).我在我的数字教科书中找到了这张幻灯片(我试图复制文本,但它不允许我复制)。

从书中滑出

What is that "lost wake" problem?什么是“丢失唤醒”问题? I tried to search in many ways but couldn't find anything regarding this.我试图以多种方式进行搜索,但找不到任何关于此的信息。

To expand on @stark's comment, suppose that thread 1 called wait() and gets preempted immediately after unlocking, but before calling block() .为了扩展@stark 的评论,假设线程 1 调用了 wait() 并在解锁后立即被抢占,但在调用 block() 之前 Assume that thread 1 is the only thread in the queue.假设线程 1 是队列中的唯一线程。 Next, suppose that a thread 2 calls signal(), calls wakeup(), and returns.接下来,假设线程2调用signal(),调用wakeup(),然后返回。 Note, that the call to wakeup() does nothing since thread 1 has not yet called block().请注意,由于线程 1 尚未调用 block(),因此调用 wakeup() 什么也不做。

Now, when thread 1 executes, it will call block(), and may potentially wait forever if no process calls signal() again.现在,当线程 1 执行时,它会调用 block(),如果没有进程再次调用 signal(),它可能会永远等待。 The call to wakeup() by thread 2 was lost since thread 1 was on the queue, but wasn't blocking yet.由于线程 1 在队列中,但尚未阻塞,因此线程 2 对唤醒()的调用丢失

Caveat警告

This really depends on system implementation.这实际上取决于系统实现。 It is feasible for wakeup() to buffer a signal if the corresponding process is not yet blocked.如果相应的进程尚未阻塞,则唤醒()可以缓冲信号。 However, I am not aware of systems that do this.但是,我不知道这样做的系统。

POSIX pthread API POSIX 线程 API

The lost-wakeup problem is mostly sidestepped when using the POSIX pthread API.在使用 POSIX pthread API 时,丢失唤醒问题大多被回避了。 Specifically, the condition variable should be protected with a lock as well.具体来说,条件变量也应该用锁保护。 This is why the man page of pthread_cond_wait says:这就是为什么 pthread_cond_wait 的手册页说:

The pthread_cond_wait() function atomically blocks the current thread
waiting on the condition variable specified by cond, and releases the
mutex specified by mutex.

The keyword above is atomically .上面的关键字是原子的

Further reading. 进一步阅读。

Follow-up Questions后续问题

  1. Can you explain more what wakeup and block really are?你能解释更多什么是唤醒和阻塞吗?

wakeup() and block() are syscalls. wakeup() 和 block() 是系统调用。 block() is used by a process to block itself until another process wakes it up. block() 被一个进程用来阻塞自己,直到另一个进程唤醒它。 This may be done, for example, to wait until another element can be removed from a queue.例如,这可以等待直到另一个元素可以从队列中移除。 wakeup() is used to wake up a process that previously called block(). wakeup() 用于唤醒之前调用 block() 的进程。

  1. Why this can't be solved by moving lock() after block() ?为什么这不能通过在 block() 之后移动 lock() 来解决?

Moving lock() after block achieves nothing, and will cause deadlock.在块之后移动 lock() 没有任何效果,并且会导致死锁。 If you meant moving unlock() after block(), then that won't work because the process will block while holding the lock, and now no other process can wake up the blocked process.如果您的意思是在 block ()之后移动unlock() ,那么这将不起作用,因为该进程将在持有锁时阻塞,现在没有其他进程可以唤醒被阻塞的进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM