使用 _beginthreadx 将结构传递给线程

发布于 2024-12-27 00:44:54 字数 936 浏览 0 评论 0原文

#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <windows.h>
#include <process.h>

using namespace std;
HANDLE ghEvents;


struct DataStructure
{
int r[2];
int h;
};


unsigned __stdcall f2(void *p)
{

DataStructure *input = (DataStructure *)p;
int i = (int)input->h;
cout <<i<<endl;

}   


int main()
{

HANDLE hThread[8];
DWORD i, dwEvent, dwThreadID;
unsigned threadID;
DataStructure input;

ghEvents = CreateEvent(NULL,FALSE,FALSE,NULL);  

for (int i = 0; i < 8; i++) 
{   
input.h=i;
hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)&input, 0, &threadID );
}

dwEvent = WaitForMultipleObjects(8,hThread,TRUE,INFINITE);       

CloseHandle(ghEvents); 
for (int i = 0; i < 8; i++) 
{
CloseHandle( hThread[i] );
}

cin.get();
return 0;

}

输出是 77777777 而不是 12345678。

我知道我必须按值传递输入而不是引用,但它一直给我一条错误消息,正确的方法是什么?

#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <windows.h>
#include <process.h>

using namespace std;
HANDLE ghEvents;


struct DataStructure
{
int r[2];
int h;
};


unsigned __stdcall f2(void *p)
{

DataStructure *input = (DataStructure *)p;
int i = (int)input->h;
cout <<i<<endl;

}   


int main()
{

HANDLE hThread[8];
DWORD i, dwEvent, dwThreadID;
unsigned threadID;
DataStructure input;

ghEvents = CreateEvent(NULL,FALSE,FALSE,NULL);  

for (int i = 0; i < 8; i++) 
{   
input.h=i;
hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)&input, 0, &threadID );
}

dwEvent = WaitForMultipleObjects(8,hThread,TRUE,INFINITE);       

CloseHandle(ghEvents); 
for (int i = 0; i < 8; i++) 
{
CloseHandle( hThread[i] );
}

cin.get();
return 0;

}

The output is 77777777 instead of 12345678.

I know i have to pass the input by value and not reference but it keeps giving me an error message, what is the proper way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鸢与 2025-01-03 00:44:54

这是我之前的答案之后的结果,如果在编译时已知线程数,这是一个更好的解决方案。

DataStructure input[8];  

... 

for (int i = 0; i < 8; i++)   
{     
   input[i].h=i;  
   hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)&input[i], 0, &threadID );  
} 

并且您需要返回一个值:

unsigned __stdcall f2(void *p)      
{      

   DataStructure *input = (DataStructure *)p;      
   int i = input->h;      
   cout <<i<<endl;      
   return 0; 
} 

This is subsequent to my previous answer as is a better solution if the number of threads is known at compile time.

DataStructure input[8];  

... 

for (int i = 0; i < 8; i++)   
{     
   input[i].h=i;  
   hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)&input[i], 0, &threadID );  
} 

And you need to return a value:

unsigned __stdcall f2(void *p)      
{      

   DataStructure *input = (DataStructure *)p;      
   int i = input->h;      
   cout <<i<<endl;      
   return 0; 
} 
江南烟雨〆相思醉 2025-01-03 00:44:54

您为每个线程提供相同DataStructure 的地址。您的输出是不确定的。根据每个线程运行的时间,它们可能会在该循环的另一次迭代之前、期间或之后进行读取。这意味着,当线程旋转并访问 input->h 时,主线程可能已经继续并将 input.h 更改为下一个迭代。

示例:

  • 主 - 循环迭代 0 将 input.h 设置为 0。
  • 主 - 循环迭代 0 以 input 作为参数启动线程 0。
  • 主 - 循环迭代 1 将 input.h 设置为 1。
  • 主 - 循环迭代 1 以 input 作为参数启动线程 1。
  • 主 - 循环迭代 2 将 input.h 设置为 2。
  • 主 - 循环迭代 2 以 input 作为参数启动线程 2。
  • 线程 1 - 启动。
  • 线程 0 - 启动。
  • 主 - 循环迭代 3 将 input.h 设置为 3。
  • 线程 0 - 将 input->h 读取为 3。
  • 线程 2 - 启动。
  • 主 - 循环迭代 3 以 input 作为参数启动线程 3。
  • 线程 1 - 将 input->h 读取为 3。
  • 线程 3 - 启动。
  • 主 - 循环迭代 4 将 input.h 设置为 4。
  • 线程 3 - 将 input->h 读取为 4。
  • 线程 2 - 读取 input->h 为 4。
  • 线程 4 - 启动。
  • 线程 4 - 将 input->h 读取为 4。

最终输出:3344

为每个线程提供不同的 DataStructure,以便它们不会尝试从同一内存地址读取。这样,就不存在竞争条件了。该术语指的是线程启动和执行顺序无法保证的事实,因此如果线程在没有完成同步的情况下访问相同的资源,它们将“竞争”。

You are giving each thread the address of the same DataStructure. Your output is non-deterministic. Depending on when each thread gets to run, they may read before, during, or after another iteration of that loop. Meaning, by the time the thread spins up and gets to access input->h, the main thread may have already continued on and changing input.h to the next iteration.

Example:

  • Main - Loop iteration 0 sets input.h to 0.
  • Main - Loop iteration 0 starts Thread 0 with input as a parameter.
  • Main - Loop iteration 1 sets input.h to 1.
  • Main - Loop iteration 1 starts Thread 1 with input as a parameter.
  • Main - Loop iteration 2 sets input.h to 2.
  • Main - Loop iteration 2 starts Thread 2 with input as a parameter.
  • Thread 1 - Starts up.
  • Thread 0 - Starts up.
  • Main - Loop iteration 3 sets input.h to 3.
  • Thread 0 - Reads input->h as 3.
  • Thread 2 - Starts up.
  • Main - Loop iteration 3 starts Thread 3 with input as a parameter.
  • Thread 1 - Reads input->h as 3.
  • Thread 3 - Starts up.
  • Main - Loop iteration 4 sets input.h to 4.
  • Thread 3 - Reads input->h as 4.
  • Thread 2 - Reads input->h as 4.
  • Thread 4 - Starts up.
  • Thread 4 - Reads input->h as 4.

Final Output: 3344

Give each thread a different DataStructure so that they are not trying to read from the same memory address. This way, there is no race-condition. The term refers to the fact that thread start up and order of execution is not guaranteed, so if threads are accessing the same resources without synchronization being done, they will "race".

執念 2025-01-03 00:44:54

第一点是:

您的数据结构没有同步,该数据结构正在传递给多个线程,并且当这些线程正在对其执行某些操作时,您已经在进行循环的下一次迭代并更改 你的数据结构的价值。

在循环内创建新的数据结构以避免出现同步问题。

First point is:

You have no synchronization in place for your datastructure which is being passed to multiple threads, and while these threads are doing something with it, you're already going through the next iteration of the loop and changing the value of your datastructure.

Create a new datastructure inside a the loop to avoid having synchronization issues.

橘味果▽酱 2025-01-03 00:44:54

当您为每个线程覆盖 input.h 的值时,您需要为每个线程创建数据结构。

因此,要修复,请将其更改为

DataStructure *input; 

...

for (int i = 0; i < 8; i++)  
{    
   input = new DataStructure ;
   input->h=i; 
   hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)input, 0, &threadID ); 
}

为了避免内存泄漏,请使用 f2 函数删除输入,即

unsigned __stdcall f2(void *p)     
{     

   DataStructure *input = (DataStructure *)p;     
   int i = input->h;     
   cout <<i<<endl;     
   delete input;
   return 0;
}

注意 此解决方案使用动态内存分配,如果编译时线程数未知,那么这是一个很好的解决方案。如果线程数已知,请参阅我的其他答案。

You need to create the data structure for each of the threads as you are overwriting the value of input.h for each of the threads.

So to fix, change it to

DataStructure *input; 

...

for (int i = 0; i < 8; i++)  
{    
   input = new DataStructure ;
   input->h=i; 
   hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)input, 0, &threadID ); 
}

And to avoid a memory leak get the f2 function to delete the input i.e.

unsigned __stdcall f2(void *p)     
{     

   DataStructure *input = (DataStructure *)p;     
   int i = input->h;     
   cout <<i<<endl;     
   delete input;
   return 0;
}

note This solution uses dynamic memory allocation as is good solution if the number of threads are unknown at compile time. See my other answer if the number of threads is known.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文