【发布时间】:2015-05-12 15:41:20
【问题描述】:
一些背景知识:我正在尝试跟踪一个让我非常头疼的错误。经过许多死胡同(见this question),我终于得到了这段代码:
#include <thread>
#include <vector>
#include <iosfwd>
#include <sstream>
#include <string>
#include <windows.h>
int main()
{
SRWLOCK srwl;
InitializeSRWLock(&srwl);
for(size_t i=0;i<1000;++i)
{
std::vector<std::thread>threads;
for(size_t j=0;j<100;++j)
{
OutputDebugString(".");
threads.emplace_back([&](){
AcquireSRWLockExclusive(&srwl);
//Code below modifies the probability to see the bug.
std::this_thread::sleep_for(std::chrono::microseconds(1));
std::wstringstream wss;
wss<<std::this_thread::get_id();
wss.str();
//Code above modifies the probability to see the bug.
ReleaseSRWLockExclusive(&srwl);});
}
for(auto&t:threads){t.join();}
OutputDebugString((std::to_string(i)+"\n").data());
}
return 0;
}
当我在 VS 2013 调试器中运行此代码时,程序会挂起并显示如下输出:
....................................................................................................0
....................................................................................................1
....................................................................................................2
...........................
奇怪的是,如果我暂停调试器并检查正在发生的事情,其中一个线程在 AcquireSRWLockExclusive 中(在 NtWaitForAlertByThreadId 中),显然程序没有理由挂起。当我点击恢复时,程序会愉快地继续打印一些内容,直到再次被阻止。
你有什么想法吗?
更多信息:
- 据我所知,此错误仅存在于 Windows 8.1 上。
- 我试过 VS2013.4 和 VS2015 RC。
- 我可以在两台不同的 Windows 8.1 计算机上重现它。
- 其中一台机器被格式化,RAM、CPU 和磁盘测试(我认为是故障,因为起初我只能观察到这台特定机器上的错误)
- 我永远无法在 Windows 7 上重现它。
- 修改 cmets 之间的代码以观察错误可能很有用。当我添加微秒睡眠时,我终于可以在另一台计算机上重现该错误。
- 使用 VS2015 RC,我可以使用简单的 std::mutex 重现相同的行为。然而,在 VS2013 上,SRWLOCK 似乎是强制观察错误的。
【问题讨论】:
-
可能是您处于死锁状态,一旦您进入调试器,它会更改同步并且死锁消失。
-
@NathanOliver 这怎么可能?代码中只有一个互斥锁。
-
程序在调试器外运行时是否挂起?
-
@RetiredNinja 它不会挂在调试器之外。
-
看着很痛苦。 std::thread 建立在并发时间之上。一分钱一磅,请改用
<ppl.h>中的Concurrency::reader_writer_lock。这可能会破坏交易,请考虑就此致电 Microsoft 支持。
标签: c++ visual-studio c++11 visual-c++