使用 _beginthreadx 将结构传递给线程
Passing structure to thread using _beginthreadx
#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。
我知道我必须通过值而不是引用传递输入,但它一直给我一条错误消息,正确的方法是什么?
这是我之前的回答之后,如果在编译时知道线程数,这是一个更好的解决方案。
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;
}
您为每个线程提供了相同DataStructure
的地址。您的输出是不确定的。根据每个线程何时运行,它们可能会在该循环的另一次迭代之前、期间或之后读取。这意味着,当线程启动并访问input->h
时,主线程可能已经继续并更改input.h
到下一次迭代。
例:
- Main - 循环迭代 0 将
input.h
设置为 0。 - Main - 循环迭代 0 以
input
作为参数启动线程 0。 - Main - 循环迭代 1 将
input.h
设置为 1。 - Main - 循环迭代 1 以
input
作为参数启动线程 1。 - Main - 循环迭代 2 将
input.h
设置为 2。 - Main - 循环迭代 2 以
input
作为参数启动线程 2。 - 线程 1 - 启动。
- 线程 0 - 启动。
- Main - 循环迭代 3 将
input.h
设置为 3。 - 线程 0 - 读取
input->h
为 3。 - 线程 2 - 启动。
- Main - 循环迭代 3 以
input
作为参数启动线程 3。 - 线程 1 - 读取
input->h
为 3。 - 线程 3 - 启动。
- Main - 循环迭代 4 将
input.h
设置为 4。 - 线程 3 - 读取
input->h
为 4。 - 线程 2 - 读取
input->h
为 4。 - 线程 4 - 启动。
- 线程 4 - 读取
input->h
为 4。
最终输出:3344
为每个线程提供不同的DataStructure
,以便它们不会尝试从相同的内存地址读取。这样,就没有竞争条件。该术语是指线程启动和执行顺序无法保证的事实,因此如果线程在没有进行同步的情况下访问相同的资源,它们将"竞争"。
第一点是:
对于传递给多个线程的数据结构,您没有同步,当这些线程对其进行某些操作时,您已经在经历循环的下一次迭代并更改数据结构的值。
在循环中创建新的数据结构以避免出现同步问题。
您需要为每个线程创建数据结构,因为要覆盖每个线程的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;
}
注意 此解决方案使用动态内存分配,如果编译时线程数未知,则此解决方案是很好的解决方案。如果线程数已知,请参阅我的另一个答案。
相关文章:
- 标准 cpp 数据结构和线程互斥锁?
- 在std::线程中使用已分配的结构数据
- 多线程和共享资源:使用C++定期将数据从缓冲区(数据结构)复制到文件
- 当并行线程访问同一数据结构的其他成员时,正确的方法可以在Visual Studio上的OpenMP上并行循环
- 无法找出此错误(将结构数组传递给函数):线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x1)
- 在多线程程序中创建OpenGL结构
- 从线程执行的函数中返回结构数组
- 如何将结构元素传递给异步线程
- 现代C++.从继续执行的工作线程返回数据结构
- OpenMP中树结构的线程安全性
- 当结构数组在主线程中填充数据时,从结构数组的低索引元素读取是否线程安全
- POSIX线程,将多个参数传递给具有结构的函数
- 使用 MFC 的结构多线程
- 从类对象和结构对象 c++ 开始线程
- 线程和结构C++
- OOP结构,可能还有一些关于线程的东西
- 工作线程队列的这种变体是某种模式或通用结构吗?
- 使用 Qt 的简单线程 gui 应用程序的结构是什么?
- 为什么valgrind(helgrind)在我的线程结构上调用虚函数时生成"Possible Data Races"
- 线程结构的性能成本:错过优化和内存分配