2

我有两个共享的全局变量

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

这很奇怪,看起来线程是按顺序工作的。那有什么问题?

谢谢。

4

3 回答 3

4

每个线程都有一个特定的时间片,在该时间片中它在被抢占之前执行。在您的示例中,时间片似乎比完成循环所需的时间长。

Sleep(0)但是,您可以通过在将关键部分留在循环中后调用来主动让出控制。

于 2011-01-19T10:10:24.837 回答
2

在您的示例中,IMO 关键部分离开/进入的速度非常快,以至于另一个线程在此时执行进入部分的速度不够快。

尝试放置一些(可能是随机的)睡眠以减慢代码速度以查看所需的效果。

注意: EnterCriticalSection 的默认超时时间为 30 天左右(意味着无穷大),因此您不能指望该函数会超时。文件说:

不能保证线程获得临界区所有权的顺序,但是,系统对所有线程都是公平的。

于 2011-01-19T10:10:28.410 回答
1

对我来说,它看起来像http://social.msdn.microsoft.com/forums/en-US/windowssdk/thread/980e5018-3ade-4823-a6dc-5ddbcc3091d5/中讨论的主题 请查看 2006 年 6 月 28 日的示例

(不幸的是,我找不到微软关于关键部分变化的原始文章)

你能在 Windows XP 上试试你的代码吗?它显示了什么?

猜想I/O 操作 (cout) 对调度的影响类似于 Sleep() 调用,因此从 Windows Vista 开始,在 CS 中执行 I/O 时,线程可能会导致其他线程的饥饿。

于 2012-05-31T07:09:20.713 回答