一个线程饿死的例子

陈硕的《Linux多线程服务端编程:使用muduo C++网络库》中2.2一节中写了一个简单的容量无限的BlockingQueue,其中出队函数enqueue()中,每次添加元素都会调用pthread_cond_signal(封装成了Condition::notify()).然后提了一个问题,如果改成只在queue.size()从0变成1的时候才调用Conditon::notify()会如何.

根据C++11写了个,BlockingQueue的实现放在了这里,test的实现放在了这里

test具体就是1个生产者4个消费者

gdb跟进用thread apply all bt得出了4个消费者状态

(gdb) thread apply all bt

Thread 5 (Thread 0x7ffff57cf700 (LWP 4223)):
#0 0x00007ffff7bc8404 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x00007ffff79664dc in std::condition_variable::wait(std::unique_lock<std::mutex>&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x000000000040b461 in std::condition_variable::wait<BlockQueue::BlockQueue<int>::dequeue()::{lambda()#1}>(std::unique_lock<std::mutex>&, BlockQueue::BlockQueue<int>::dequeue()::{lambda()#1}) (this=0x612230 <queue+40>, __lock=..., __p=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/condition_variable:93
#3 0x0000000000409a0a in BlockQueue::BlockQueue<int>::dequeue (this=0x612208 <queue>) at /home/hr/code/somecode/test/../BlockQueue/BlockQueue.h:46
#4 0x0000000000409487 in test_pop () at /home/hr/code/somecode/test/testStarvation.cc:24
#5 0x000000000040c66f in std::_Bind_simple<int (*())()>::_M_invoke<>(std::_Index_tuple<>) (this=0x6136f0) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1731
#6 0x000000000040c645 in std::_Bind_simple<int (*())()>::operator()() (this=0x6136f0) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1720
#7 0x000000000040c3f9 in std::thread::_Impl<std::_Bind_simple<int (*())()> >::_M_run() (this=0x6136d8) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:115
#8 0x00007ffff7969a60 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x00007ffff7bc4184 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#10 0x00007ffff70d0ffd in clone () from /lib/x86_64-linux-gnu/libc.so.6

Thread 4 (Thread 0x7ffff5fd0700 (LWP 4222)):
#0 0x00007ffff7bc8404 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x00007ffff79664dc in std::condition_variable::wait(std::unique_lock<std::mutex>&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x000000000040b461 in std::condition_variable::wait<BlockQueue::BlockQueue<int>::dequeue()::{lambda()#1}>(std::unique_lock<std::mutex>&, BlockQueue::BlockQueue<int>::dequeue()::{lambda()#1}) (this=0x612230 <queue+40>, __lock=..., __p=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/condition_variable:93
#3 0x0000000000409a0a in BlockQueue::BlockQueue<int>::dequeue (this=0x612208 <queue>) at /home/hr/code/somecode/test/../BlockQueue/BlockQueue.h:46
#4 0x0000000000409487 in test_pop () at /home/hr/code/somecode/test/testStarvation.cc:24
#5 0x000000000040c66f in std::_Bind_simple<int (*())()>::_M_invoke<>(std::_Index_tuple<>) (this=0x613580) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1731
#6 0x000000000040c645 in std::_Bind_simple<int (*())()>::operator()() (this=0x613580) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1720
#7 0x000000000040c3f9 in std::thread::_Impl<std::_Bind_simple<int (*())()> >::_M_run() (this=0x613568) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:115
#8 0x00007ffff7969a60 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x00007ffff7bc4184 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#10 0x00007ffff70d0ffd in clone () from /lib/x86_64-linux-gnu/libc.so.6

Thread 3 (Thread 0x7ffff67d1700 (LWP 4221)):
#0 0x00007ffff7bc8404 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x00007ffff79664dc in std::condition_variable::wait(std::unique_lock<std::mutex>&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x000000000040b461 in std::condition_variable::wait<BlockQueue::BlockQueue<int>::dequeue()::{lambda()#1}>(std::unique_lock<std::mutex>&, BlockQueue::BlockQueue<int>::dequeue()::{lambda()#1}) (this=0x612230 <queue+40>, __lock=..., __p=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/condition_variable:93
#3 0x0000000000409a0a in BlockQueue::BlockQueue<int>::dequeue (this=0x612208 <queue>) at /home/hr/code/somecode/test/../BlockQueue/BlockQueue.h:46
#4 0x0000000000409487 in test_pop () at /home/hr/code/somecode/test/testStarvation.cc:24
#5 0x000000000040c66f in std::_Bind_simple<int (*())()>::_M_invoke<>(std::_Index_tuple<>) (this=0x613410) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1731
#6 0x000000000040c645 in std::_Bind_simple<int (*())()>::operator()() (this=0x613410) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1720
#7 0x000000000040c3f9 in std::thread::_Impl<std::_Bind_simple<int (*())()> >::_M_run() (this=0x6133f8) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:115
#8 0x00007ffff7969a60 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x00007ffff7bc4184 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#10 0x00007ffff70d0ffd in clone () from /lib/x86_64-linux-gnu/libc.so.6

Thread 1 (Thread 0x7ffff7fd3780 (LWP 4215)):
#0 main () at /home/hr/code/somecode/test/testStarvation.cc:42
#1 0x00007ffff6ff4f45 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x0000000000409359 in _start ()

而gdb的p queue.queue_.size()则得出了

[Thread 0x7ffff67d1700 (LWP 9075) exited]
$1 = 9

可见消费者生产的2个线程并未被消费,因为在第一条插入之后触发0到1的转变,触发notify,但是由于接下来的pop和第二此push的顺序不能确定,即:

queue_.pop_front()               与               if(queue_.size() == 1)

如果是pop晚于了push而第二次锁lock的是push而非pop,那么只有一个消费者会被唤醒,其他的消费者就陷入了starvation而永远陷入pthread_cond_wait()等待中

原文链接: https://www.cnblogs.com/lovewisdom/p/7819332.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    一个线程饿死的例子

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/263137

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午3:36
下一篇 2023年2月14日 下午3:37

相关推荐