【发布时间】:2020-07-20 10:39:29
【问题描述】:
我正在上操作系统课,我的教授给了我们这个作业。
“将 __asm mfence 放置在适当的位置。”
这个问题是关于使用多线程及其副作用。
主线程正在增加 shared_var,但 thread_1 正在同时进行。
因此,当代码增加 2000000 次时,shared_var 变为 199048359.000。
教授说__asm mfence 会解决这个问题。但是,我不知道该放在哪里。
我正在尝试在 google、github 和此处搜索问题,但找不到来源。
我不知道这是一个愚蠢的问题,因为我的专业不是计算机科学。
另外,我想知道为什么这段代码显示 199948358.0000 而不是 2000000.00
任何帮助将不胜感激。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
int turn;
int interested[2];
void EnterRegion(int process);
void LeaveRegion(int process);
DWORD WINAPI thread_func_1(LPVOID lpParam);
volatile double shared_var = 0.0;
volatile int job_complete[2] = {0, 0};
int main(void)
{
DWORD dwThreadId_1, dwThrdParam_1 = 1;
HANDLE hThread_1;
int i, j;
// Create Thread 1
hThread_1 = CreateThread(
NULL, // default security attributes
0, // use default stack size
thread_func_1, // thread function
&dwThrdParam_1, // argument to thread function
0, // use default creation flags
&dwThreadId_1
); // returns the thread identifier
// Check the return value for success.
if (hThread_1 == NULL)
{
printf("Thread 1 creation error\n");
exit(0);
}
else
{
CloseHandle( hThread_1 );
}
/* I am main thread */
/* Now Main Thread and Thread 1 runs concurrently */
for (i = 0; i < 10000; i++)
{
for (j = 0; j < 10000; j++)
{
EnterRegion(0);
shared_var++;
LeaveRegion(0);
}
}
printf("Main Thread completed\n");
job_complete[0] = 1;
while (job_complete[1] == 0) ;
printf("%f\n", shared_var);
_getch();
ExitProcess(0);
}
DWORD WINAPI thread_func_1(LPVOID lpParam)
{
int i, j;
for (i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
{
EnterRegion(1);
shared_var++;
LeaveRegion(1);
}
}
printf("Thread_1 completed\n");
job_complete[1] = 1;
ExitThread(0);
}
void EnterRegion(int process)
{
_asm mfence;
int other;
other = 1 - process;
interested[process] = TRUE;
turn = process;
while (turn == process && interested[other] == TRUE) {}
_asm mfence;
}
void LeaveRegion(int process)
{
_asm mfence;
interested[process] = FALSE;
_asm mfence;
}
【问题讨论】:
-
你可以提到 win32 标签而不是更广泛的操作系统标签。您可能还想看看stackoverflow.com/a/8561459/8155816,似乎没有答案,但围绕它进行了很多讨论。
-
@alc:这个答案在这里不适用。
shared_var被初始化为0.0并且总是以1.0递增。这将总是产生一个没有小数部分的浮点值。浮点值可以准确地表示任何非小数(在其范围内)。2000000.00在double可以准确表示的非小数范围内。 -
因此我说 cmets 和周围的对话而不是答案可能很有趣。 ^^'
标签: c winapi memory operating-system barrier