c - 设置共享变量时应该使用临界区还是内存屏障?
问题描述
假设我有以下代码:
/* Global Variables */
int flag = 0;
int number1;
int number2;
//------------------------------------
/* Thread A */
number1 = 12345;
number2 = 678910;
flag = 1;
//------------------------------------
/* Thread B */
while (flag == 0) {}
printf("%d", number1);
printf("%d", number2);
在Thread A中,代码可能不会按顺序执行,可能会像这样执行:
/* Thread A */
flag = 1;
number1 = 12345;
number2 = 678910;
为了防止这种情况,我应该使用内存屏障。
但我不确定是否应该使用常规内存屏障,例如:
/* Thread A */
number1 = 12345;
number2 = 678910;
MEMORY_BARRIER_GOES_HERE
flag = 1;
或者如果我应该使用关键部分,例如:
/* Thread A */
number1 = 12345;
number2 = 678910;
EnterCriticalSection(&cs);
flag = 1;
LeaveCriticalSection(&cs);
解决方案
试图巧妙地使用无锁线程模型(障碍、原子、互锁操作等)来保护多个变量而不是标准锁定机制只会导致错误。
您需要用锁保护所有变量(number1
、、number2
和flag
)(关键部分)
线程 A:
EnterCriticalSection(&cs);
flag = 1;
number1 = 12345;
number2 = 678910;
LeaveCriticalSection(&cs);
线程 B:
while (1)
{
int n1, n2;
EnterCriticalSection(&cs);
if (flag)
{
n1 = number1;
n2 = number2;
break;
}
LeaveCriticalSection(&cs);
}
printf("%d", n1);
printf("%d", n2);
此外,在 Windows 上,您可以避免整个while (flag == 0) {}
循环使用Conditional Variable烧毁 CPU 内核。从连续轮询机制切换到基于通知的机制将产生比尝试执行棘手的联锁操作更好的性能结果。
更好的:
线程 A:
EnterCriticalSection(&cs);
flag = 1;
number1 = 12345;
number2 = 678910;
LeaveCriticalSection(&cs);
WakeAllConditionVariable(&conditional_variable);
线程 B:
EnterCriticalSection(&cs);
while (flag == 0)
{
// This will atomically Leave the CS and block until the conditional_variable is fired by the other thread
SleepConditionVariableCS(&conditional_variable, &cs, INFINITE);
// After it returns, it will re-enter the CS.
}
n1 = number1;
n2 = number2;
LeaveCriticalSection(&cs);
printf("%d", n1);
printf("%d", n2);
推荐阅读
- python-3.x - 有人可以解释为什么 Python3.x `in` 运算符在这里不起作用吗?
- python - 滚动条不会出现在 PyQt5 自定义标签中
- flutter - 我们可以在 Flutter 中裁剪带有点和大小的图像吗?
- c++ - 为什么它停止并以退出代码 11 结束?
- java - 登录过程:未阅读我在 selenium 中的 else 语句
- javascript - 使用 nodejs 在 Twitter 中按位置搜索
- c# - 在对超过 100,000 行 Excel 文档(在 C# 中)执行 ETL 操作时寻找有关提高性能的建议
- swift - Swift 包无法为 watchOS 编译
- machine-learning - 如何设置LSTM的参数
- javascript - VueJS 动态 v-model 目标