Windows Critical Section奇怪的行为

时间:2011-01-19 10:03:54

标签: c++ winapi mutex critical-section

我有两个共享的全局变量

int a = 0;
int b = 0;

和两个线程

// thread 1
for (int i = 0; i < 10; ++i) {
    EnterCriticalSection(&sect);
    a++;
    b++;
    std::cout << a " " << b << std::endl;
    LeaveCriticalSection(&sect);
}

// thread2
for (int i = 0; i < 10; ++i) {
    EnterCriticalSection(&sect);
    a--;
    b--;
    std::cout << a " " << b << std::endl;
    LeaveCriticalSection(&sect);
}

代码始终打印以下输出

  

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

这很奇怪,看起来线程正在等待......这有什么问题?

感谢。

3 个答案:

答案 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。