Передача структуры в поток с помощью _beginthreadx - PullRequest
0 голосов
/ 13 января 2012
#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.

Я знаю, что должен передать ввод по значению, а не по ссылке, но он постоянно выдает мне сообщение об ошибке, как правильно это сделать?

Ответы [ 4 ]

1 голос
/ 13 января 2012

Это после моего предыдущего ответа, так как это лучшее решение, если число потоков известно во время компиляции.

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; 
} 
1 голос
/ 13 января 2012

Вы даете каждому потоку адрес того же DataStructure. Ваш вывод недетерминирован. В зависимости от того, когда каждый поток запускается, он может читать до, во время или после другой итерации этого цикла. Это означает, что к тому моменту, когда поток раскручивается и получает доступ к input->h, основной поток, возможно, уже продолжил и меняет input.h на следующую итерацию.

Пример:

  • Main - Итерация цикла 0 устанавливает input.h в 0.
  • Main - Итерация цикла 0 запускает поток 0 с input в качестве параметра.
  • Main - Итерация цикла 1 устанавливает input.h в 1.
  • Main - Итерация цикла 1 запускает поток 1 с input в качестве параметра.
  • Main - Итерация цикла 2 устанавливает input.h в 2.
  • Main - Итерация цикла 2 запускает поток 2 с input в качестве параметра.
  • Тема 1 - запускается.
  • Тема 0 - запускается.
  • Main - Итерация цикла 3 устанавливает input.h в 3.
  • Тема 0 - Читается input->h как 3.
  • Тема 2 - запускается.
  • Main - Итерация цикла 3 запускает поток 3 с input в качестве параметра.
  • Тема 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, чтобы они не пытались читать с одного и того же адреса памяти. Таким образом, нет расы. Термин относится к тому факту, что запуск потока и порядок выполнения не гарантируются, поэтому, если потоки обращаются к одним и тем же ресурсам без выполнения синхронизации, они будут «гоняться».

0 голосов
/ 13 января 2012

Первая точка:

У вас нет синхронизации для вашей структуры данных, которая передается нескольким потокам, и хотя эти потоки что-то с ней делают, вы уже проходите следующую итерациюцикл и изменяют значение вашей структуры данных.

Создайте новую структуру данных внутри цикла, чтобы избежать проблем с синхронизацией.

0 голосов
/ 13 января 2012

Вам необходимо создать структуру данных для каждого из потоков, поскольку вы перезаписываете значение 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;
}

note Это решение использует динамическое распределение памяти, что является хорошим решением, если число потоковнеизвестно во время компиляции.Смотрите мой другой ответ, если число потоков известно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...