我有两个共享的全局变量
int a = 0;
int b = 0;
和两个线程
// thread 1
for (int i = 0; i < 10; ++i) {
EnterCriticalSection(§);
a++;
b++;
std::cout << a " " << b << std::endl;
LeaveCriticalSection(§);
}
// thread2
for (int i = 0; i < 10; ++i) {
EnterCriticalSection(§);
a--;
b--;
std::cout << a " " << b << std::endl;
LeaveCriticalSection(§);
}
代码始终打印以下输出
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
9 9
8 8
7 7
6 6
5 5
4 4
3 3
2 2
1 1
0 0
这很奇怪,看起来线程正在等待......这有什么问题?
感谢。
答案 0 :(得分:4)
每个线程都有一个特定的时间片,在此时间片段被抢占之前执行。在您的示例中,时间片似乎比完成循环所需的时间长。
但是,在将临界区留在循环内后,您可以通过调用Sleep(0)
来主动控制。
答案 1 :(得分:2)
你的例子中的IMO关键部分离开/输入是如此之快,以至于另一个线程不够快在此刻执行输入部分。
尝试放置一些(可能是随机的)睡眠以减慢代码以查看所需的效果。
注意:强> EnterCriticalSection的默认超时大约为30天(意味着无限),因此您不能指望该功能会超时。 documentation说:
无法保证线程获取关键部分所有权的顺序,但是,系统对所有线程都是公平的。
答案 2 :(得分:1)
对我来说,它看起来像http://social.msdn.microsoft.com/forums/en-US/windowssdk/thread/980e5018-3ade-4823-a6dc-5ddbcc3091d5/中讨论的主题 请看2006年6月28日的例子
(遗憾的是我无法找到微软讲述CriticalSection变化的原始文章)
您可以在Windows XP上试用代码吗?它显示了什么?
我猜测 I / O操作(cout)与Sleep()调用类似地影响调度,因此从Windows Vista开始,当在I / O内部执行I / O时,线程可能导致其他线程的饥饿一个CS。