如果足够多的活动,boost::mutex 可以锁定操作系统吗?
Posted
技术标签:
【中文标题】如果足够多的活动,boost::mutex 可以锁定操作系统吗?【英文标题】:Can boost::mutex lock out an OS if enough are active? 【发布时间】:2013-02-18 18:29:48 【问题描述】:我正在处理一个中间处理线程的生产者消费者问题。当我运行 200 个这样的应用程序时,它会在大量连接超时时将系统锁定在 win7 中。不幸的是,不是以我知道如何调试它的方式。系统变得无响应,我必须使用电源按钮重新启动它。它在我的 mac 上运行良好,奇怪的是,它在安全模式下的 windows 下运行良好。
我使用的是 boost 1.44,因为它是宿主应用程序使用的。
这是我的队列。我的意图是队列的大小是同步的。我已经操纵它使用timed_wait
来确保我没有丢失通知,尽管我没有发现效果有什么不同。
class ConcurrentQueue
public:
void push(const std::string& str, size_t notify_size, size_t max_size);
std::string pop();
private:
std::queue<std::string> queue;
boost::mutex mutex;
boost::condition_variable cond;
;
void ConcurrentQueue::push(
const std::string& str, size_t notify_size, size_t max_size)
size_t queue_size;
boost::mutex::scoped_lock lock(mutex);
if (queue.size() < max_size)
queue.push(str);
queue_size = queue.size();
if (queue_size >= notify_size)
cond.notify_one();
std::string ConcurrentQueue::pop()
boost::mutex::scoped_lock lock(mutex);
while (!queue.size())
cond.wait(lock);
std::string str = queue.front();
queue.pop();
return str;
这些线程使用以下队列使用 libcurl 进行处理和发送。
boost::shared_ptr<ConcurrentQueue> queue_a(new ConcurrentQueue);
boost::shared_ptr<ConcurrentQueue> queue_b(new ConcurrentQueue);
void prod_run(size_t iterations)
try
// stagger startup
boost::this_thread::sleep(
boost::posix_time::seconds(random_num(0, 25)));
size_t save_frequency = random_num(41, 97);
for (size_t i = 0; i < iterations; i++)
// compute
size_t v = 1;
for (size_t j = 2; j < (i % 7890) + 4567; j++)
v *= j;
v = std::max(v % 39484, v % 85783);
// save
if (i % save_frequency == 0)
std::string iv =
boost::str( boost::format("%1%=%2%") % i % v );
queue_a->push(iv, 1, 200);
sleep_frame();
catch (boost::thread_interrupted&)
void prodcons_run()
try
for (;;)
std::string iv = queue_a->pop();
queue_b->push(iv, 1, 200);
catch (boost::thread_interrupted&)
void cons_run()
try
for (;;)
std::string iv = queue_b->pop();
send_http_post("http://127.0.0.1", iv);
catch (boost::thread_interrupted&)
我对以这种方式使用互斥锁的理解不应使系统无响应。如果有的话,我的应用会死锁并永远休眠。
有没有什么方法可以同时拥有 200 个这样的场景,而情况并非如此?
更新:
当我重新启动计算机时,大多数时候我需要重新插入 USB 键盘以使其响应。鉴于司机的评论,我认为这可能是相关的。我尝试更新北桥驱动程序,尽管它们是最新的。我会看看是否还有其他需要注意的驱动程序。
更新:
我观察了内存、非分页池、cpu、句柄、端口,在系统响应时,它们都没有处于惊人的速度。可能最后会出现一些尖峰,尽管我看不到。
更新:
当系统挂起时,它会停止渲染并且不响应键盘。它渲染的最后一帧仍然存在。系统听起来它仍在运行,当系统恢复运行时,事件查看器中没有任何内容表明它崩溃了。也没有故障转储文件。我将此解释为操作系统被阻止执行。
【问题讨论】:
“奇怪的是,它在安全模式下的 Windows 中运行良好”——这表明某些 3rd 方驱动程序正在搞砸。可能是防病毒软件或防火墙。您可以尝试卸载这些类型的软件包,看看之后是否会突然开始工作。 您查看过内存使用情况吗?如果应用程序使用大量内存,您可能会发现系统无响应。在安全模式下运行将减少系统的负载。但我同意,AV 或防火墙似乎是一个可能的候选者——尤其是 AV。反病毒软件会与很多东西挂钩,并且通常会通过“所有东西都必须通过这个狭窄的洞”类型的行为来使系统无响应。 @MichaelBurr 根据驱动程序更新了评论。接下来我会尝试看看。感谢 cmets! @MatsPetersson 根据指标更新评论。我不确定是否还有其他需要检查的地方。 您能否澄清一下:是您的应用程序挂起/断开连接,还是操作系统本身? 【参考方案1】:互斥锁会锁定使用相同锁的其他应用程序。操作系统使用的任何互斥锁都不应该(直接)对任何应用程序可用。
当然,如果互斥锁是以某种方式使用操作系统实现的,它很可能会调用操作系统,从而使用 CPU 资源。但是,互斥锁不会导致比应用程序以任何其他方式使用 CPU 资源更糟糕的行为。
当然,如果你以不恰当的方式使用锁,应用程序的不同部分就会陷入死锁,因为函数 1 获取锁 A,然后函数 2 获取锁 B。如果函数 1 尝试获取锁 B ,而函数 2 在释放各自的锁之前尝试获取锁 A,则您遇到了死锁。这里的技巧是始终以相同的顺序获取多个锁。所以如果同时需要两把锁,总是先获取锁A,再获取锁B。
死锁不应该像这样影响操作系统 - 如果有的话,它会使它变得更好,但是如果应用程序在死锁的情况下以某种方式“行为不端”,它可能会通过大量调用操作系统而导致问题 - 例如,如果锁定由:
while (!trylock(lock))
/// do nothing here
它可能会导致系统使用高峰。
【讨论】:
但特别是如果应用程序死锁(即所有线程进入停止状态),操作系统永远不会无响应。除非 Windows 调度程序比我想象的更糟糕,但这又会与它在安全模式下工作的方面发生冲突。 我想知道你为什么要包含关于死锁的段落?我可能会在这里忽略一些重要的事情,但是……以上是关于如果足够多的活动,boost::mutex 可以锁定操作系统吗?的主要内容,如果未能解决你的问题,请参考以下文章
CUDA主机代码的互斥锁? boost::mutex 由于使用 nvcc 重新定义了 BOOST_COMPILER 没有解决方案
boost::interprocess_mutex 与进程本地 boost::mutex
C++ 多线程 读锁之后不能跟写锁 shared_lock之后不能跟unique_lock 死锁 解决方案
/include/boost/thread/pthread/mutex.hpp:111: boost::mutex::~mutex(): Assertion `!res' 失败