| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
| #include <iostream>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;
#endif
using namespace std;
static DWORD WINAPI FirstThread(void* pv); // Прототипы функций
static DWORD WINAPI SecondThread(void* pv); // которые будут участвовать в гонке потоков
HANDLE g_hSemaphore; // Обьявляем Хендл семафора
HANDLE hStdout; // Хендл вывода информации в консоли
int Lid = 0, g_nIndex = 0; // Флаг, определяющий поток завершённый первым(лидерство), количество синхронизируемых потоков
int a[20], IndexResours = 0; // Общий ресурс и его индекс
LONG MaxCount = 3; // Максимальное количество синхронизируемых семафором потоков
static DWORD WINAPI FirstThread(void* pv) //Функция FirstThread для работы с потоком (static - сохраняет значение во время работы программы)
{
COORD pos; // Переменная, которая будет хранить текущую координату курсора
pos.X = 3; // Столбец отображения задержки первого потока
BOOL fDone = FALSE; // Флаг отработки потока
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hSemaphore, INFINITE); // Ожидание запуска семафора на длительном интервале времени
if (g_nIndex >= MaxCount) // Проверяю, не создано ли потоков больше чем максимальное кол-во потоков
fDone = TRUE; //выходим из цикла
else //или
{
g_nIndex++; // Количество потоков увеличиваю на 1
for (int i = 0; i <= 10; i++) // Начинаю цикл для инициализации массива 10 временных задержек
{
srand(time(NULL)); // Включаю генератор случайных чисел
IndexResours++;
a[IndexResours - 1] = rand() % 1000;// Генерирую задержку первого потока (от 0 до 1000 миллисекунд)
pos.Y = i;
SetConsoleCursorPosition(hStdout, pos); // Устанавливаю курсор в i - тую строку
cout << a[IndexResours - 1] << " First"; // Вывожу текущую задержку для первого потока
Sleep(a[IndexResours - 1]); // Осуществляю задерку на текущее количество миллисекунд
}
}
::ReleaseSemaphore(g_hSemaphore, 1, 0); // Освобождаю семафор от данного потока
}
if (!Lid) // Если лидирующий поток не определён, то делаю данный лидирующим
Lid = 1;
return 0;
}
static DWORD WINAPI SecondThread(void* pv)
{
COORD pos;// Переменная, которая будет хранить текущую координату курсора
int Speed2[10]; // Массив задержек второго потока
pos.X = 25;// Столбец отображения задержки второго потока
BOOL fDone = FALSE;// Флаг отработки потока
while (!fDone)
{
::WaitForSingleObject(g_hSemaphore, INFINITE);// Ожидание запуска семафора на длительном интервале времени
if (g_nIndex >= MaxCount)// Проверяю, не создано ли потоков больше чем максимальное кол-во потоков
fDone = TRUE;
else
{
g_nIndex++;// Количество потоков увеличиваю на 1
for (int i = 0; i <= 10; i++)// Начинаю цикл для инициализации массива 10-ти временных задержек
{
IndexResours++;
a[IndexResours - 1] = rand() % 1000;// Генерирую задержку второго потока (от 0 до 1000 миллисекунд)
pos.Y = i;
SetConsoleCursorPosition(hStdout, pos);// Устанавливаю курсор в i - тую строку
cout << a[IndexResours - 1] << " Second"; // Вывожу текущую задержку для второго потока
Sleep(a[IndexResours - 1]); // Осуществляю задерку на текущее количество миллисекунд
}
}
::ReleaseSemaphore(g_hSemaphore, 1, 0);// Освобождаю семафор от данного потока
}
if (!Lid)// Если лидирующий поток не определён, то делаю данный лидирующим
Lid = 2;
return 0;
}
static DWORD WINAPI ThirdThread(void* pv)
{
COORD pos;// Переменная, которая будет хранить текущую координату курсора
int Speed3[10]; // Массив задержек второго потока
pos.X = 45;// Столбец отображения задержки второго потока
BOOL fDone = FALSE;// Флаг отработки потока
while (!fDone)
{
::WaitForSingleObject(g_hSemaphore, INFINITE);// Ожидание запуска семафора на длительном интервале времени
if (g_nIndex >= MaxCount)// Проверяю, не создано ли потоков больше чем максимальное кол-во потоков
fDone = TRUE;
else
{
g_nIndex++;// Количество потоков увеличиваю на 1
for (int i = 0; i <= 10; i++)// Начинаю цикл для инициализации массива 10-ти временных задержек
{
IndexResours++;
a[IndexResours - 1] = rand() % 1000;// Генерирую задержку второго потока (от 0 до 1000 миллисекунд)
pos.Y = i;
SetConsoleCursorPosition(hStdout, pos);// Устанавливаю курсор в i - тую строку
cout << a[IndexResours - 1] << " Third";// Вывожу текущую задержку для третьего потока
Sleep(a[IndexResours - 1]);// Осуществляю задерку на текущее количество миллисекунд
}
}
::ReleaseSemaphore(g_hSemaphore, 1, 0);// Освобождаю семафор от данного потока
}
if (!Lid)// Если лидирующий поток не определён, то делаю данный лидирующим
Lid = 3;
return 0;
}
int main()
{
int nRetCode = 0;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dw; // Обьект синхронизации
LONG g_iCount = 3; // начальное значение семафора
HANDLE hThreads[3]; // Массив Хендлов потоков
g_hSemaphore = ::CreateSemaphore(NULL, g_iCount, MaxCount, NULL); // Создаем семафор и инициализируем его Хендл
hThreads[0] = ::CreateThread(NULL, 0, FirstThread, NULL, 0, &dw); // Создаем потоки
hThreads[1] = ::CreateThread(NULL, 0, SecondThread, NULL, 0, &dw);
hThreads[2] = ::CreateThread(NULL, 0, ThirdThread, NULL, 0, &dw); // и инициализируем Массив Хендлов потоков
::ResumeThread(hThreads[0]); //Запускаем потоки
::ResumeThread(hThreads[1]);
::ResumeThread(hThreads[2]);
::WaitForMultipleObjects(3, hThreads, TRUE, INFINITE); // Ожидаем окончание работы 3 потоков на очень длительном интервале времени
::CloseHandle(hThreads[0]); // Закрываем созданные потоки
::CloseHandle(hThreads[1]);
::CloseHandle(hThreads[2]);
::CloseHandle(g_hSemaphore); // и сам семафор
switch (Lid) //определяем поток, который завершился первым { case 1 : cout << "n nepBbIu' noTok *I*uHuLLIupoBaJI nepBbIM!!!n"; break;
{
case 1:
cout << "\n FirstThread finished\n";
break;
case 2:
cout << "\n SecondThread finished\n";
break;
case 3:
cout << "\n ThirdThread finished\n";
break;
default:
break;
return 0;
}
} |
|
Добавлено через 4 минуты
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
| #include <iostream> //библиотека для ввода-вывода
#include <windows.h> //подключаем библиотеку windows.h
int g_nIndex = 0; //создание переменной для работы с массивом
const int MAX_TIMES = 1000; //размер массива данных
DWORD g_dwTimes[MAX_TIMES]; //создание массива, с которым работают потоки
HANDLE g_hMutex = NULL; // переменная для создания мьютекса
DWORD dwThreadID; // ID потока
int a = 10;
static DWORD WINAPI FirstThread(void* pv) //Функция FirstThread для работы с потоком (static - сохраняет значение во время работы программы)
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //когда переменная больше (1000)
fDone = TRUE; //выходим из цикла
else // или
{
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
std::cout << "FirstThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для первого потока
}
::ReleaseMutex(g_hMutex); //Освобождаем Mutex
}
return 0; //выход из функции FirstThread
}
static DWORD WINAPI SecondThread(void* pv) //Функция SecondThread для работы с потоком (static - сохраняет значение во время работы программы
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //когда переменная больше (1000)
fDone = TRUE; //выходим из цикла
else // или
{
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
std::cout << "SecondThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для первого потока
}
::ReleaseMutex(g_hMutex); //Освобождаем Mutex
}
return 0;
}
int main(int argc, char* argv[]) //главная функция для работы с потоком
{
HANDLE hThreads[2]; //создание массива типа HANDLE (любой тип данных)
g_hMutex = ::CreateMutex(NULL, FALSE, NULL); //Создаем Mutex, атрибут безопастности, флаг начального владельца, имя объекта
hThreads[0] = ::CreateThread(NULL, 0, FirstThread, NULL, 0,
&dwThreadID); /*создание первого потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока,
флаг, записать dwThreadID созданного потока)*/
hThreads[1] = ::CreateThread(NULL, 0, SecondThread, NULL,
0, &dwThreadID); /*создание первого потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока,
флаг, записать dwThreadID созданного потока)*/
::WaitForMultipleObjects(2, hThreads, TRUE, INFINITE); // (кол-во ожидаемых объектов, тип ожидаемых объектов, ожидать все объекты, максимальное время ожидания)
::CloseHandle(hThreads[0]); // закрываем первый поток
::CloseHandle(hThreads[1]); // закрываем второй поток
::CloseHandle(g_hMutex); // закрываем Mutex
return 0;
} |
|
Добавлено через 12 минут
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
| #include <windows.h> //подключаем библиотеку windows.h
#include <iostream> //библиотека для ввода-вывода
int g_nIndex = 0; //создание переменной для работы с массивом
const int MAX_TIMES = 50; //размер массива данных
DWORD g_dwTimes[MAX_TIMES]; //создание массива, с которым работают потоки
HANDLE g_hMutex; // переменная для создания мьютекса
int a = 1;
static DWORD WINAPI FirstThread(void* pv) //Функция FirstThread для работы с потоком (static - сохраняет значение во время работы программы)
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //если g_nIndex больше (1000)
fDone = TRUE; //выходим из цикла
else //или
{
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
HANDLE hOUTPUT = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOUTPUT, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
std::cout << "FirstThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для первого потока
}
::ReleaseMutex(g_hMutex); //Освобождаю Mutex
}
return 0; //выход из функции FirstThread
}
static DWORD WINAPI SecondThread(void* pv) //Функция SecondThread для работы с потоком (static - сохраняет значение во время работы программы)
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //если g_nIndex больше (1000)
fDone = TRUE; //выходим из цикла
else //или
{
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
HANDLE hOUTPUT = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOUTPUT, FOREGROUND_GREEN | FOREGROUND_BLUE);
std::cout << "SecondThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для второго потока
}
::ReleaseMutex(g_hMutex); //Освобождаю Mutex
}
return 0; //выход из функции SecondThread
}
static DWORD WINAPI ThirdThread(void* pv) //Функция ThirdThread для работы с потоком (static - сохраняет значение во время работы программы)
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //если g_nIndex больше (1000)
fDone = TRUE; //выходим из цикла
else //или
{
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
HANDLE hOUTPUT = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOUTPUT, FOREGROUND_RED | FOREGROUND_INTENSITY);
std::cout << "ThirdThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для третьего потока
}
::ReleaseMutex(g_hMutex); //Освобождаю Mutex
}
return 0; //выход из функции ThirdThread
}
static DWORD WINAPI FourThread(void* pv) //Функция FourThread для работы с потоком (static - сохраняет значение во время работы программы)
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //если g_nIndex больше (1000)
fDone = TRUE; //выходим из цикла
else //или
{
HANDLE hOUTPUT = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOUTPUT, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
std::cout << "FourThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для четвёртого потока
}
::ReleaseMutex(g_hMutex); //Освобождаю Mutex
}
return 0; //выход из функции FourThread
}
static DWORD WINAPI FiveThread(void* pv) //Функция FiveThread для работы с потоком (static - сохраняет значение во время работы программы)
{
BOOL fDone = FALSE; //переменная, работает с циклом, когда FALSE
while (!fDone) //запуск цикла, работает пока fDone = FALSE
{
::WaitForSingleObject(g_hMutex, INFINITE); /*g_hMutex, ID объекта
INFINITE время ожидания в миллисекундах
WaitForSingleObject ждём появление потока, потом Mutex блокирует доступ другим потокам*/
if (g_nIndex >= MAX_TIMES) //если g_nIndex больше (1000)
fDone = TRUE; //выходим из цикла
else //или
{
HANDLE hOUTPUT = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOUTPUT, FOREGROUND_INTENSITY | FOREGROUND_INTENSITY);
g_dwTimes[g_nIndex++] = a++; //заполняется массив временем с начала работы системы
std::cout << "FiveThread " << g_dwTimes[g_nIndex - 1] << std::endl; // Вывожу текущее значение для пятого потока
}
::ReleaseMutex(g_hMutex); //Освобождаю Mutex
}
return 0; //выход из функции FiveThread
}
int main(int argc, char* argv[]) //главная функция для работы с потоком
{
HANDLE hThreads[5]; //создание массива типа HANDLE (любой тип данных)
DWORD dwThreadID; // ID потока
hThreads[0] = ::CreateThread(NULL, 0, FirstThread, NULL,
CREATE_SUSPENDED, &dwThreadID);/*создание первого потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока,
CREATE_SUSPENDED позволяет создаёт поток в спящем режиме, и он
не запускается до тех пор пока не будет вызвана функция ResumeThread,
записать dwThreadID созданного потока*/
hThreads[1] = ::CreateThread(NULL, 0, SecondThread, NULL,
CREATE_SUSPENDED, &dwThreadID); /*создание второго потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока,
CREATE_SUSPENDED позволяет создаёт поток в спящем режиме, и он
не запускается до тех пор пока не будет вызвана функция ResumeThread,
записать dwThreadID созданного потока*/
hThreads[2] = ::CreateThread(NULL, 0, ThirdThread, NULL,
CREATE_SUSPENDED, &dwThreadID); /*создание третьего потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока,
CREATE_SUSPENDED позволяет создаёт поток в спящем режиме, и он
не запускается до тех пор пока не будет вызвана функция ResumeThread,
записать dwThreadID созданного потока*/
hThreads[3] = ::CreateThread(NULL, 0, FourThread, NULL,
CREATE_SUSPENDED, &dwThreadID); /*создание четвёртого потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока
записать dwThreadID созданного потока*/
g_hMutex = ::CreateMutex(NULL, FALSE, NULL);//создаем мьютекс после 3 потока
hThreads[4] = ::CreateThread(NULL, 0, FiveThread, NULL,
0, &dwThreadID); /*создание пятого потока (дескриптор безопасности (по умолчанию - NULL),
размер стека в байтах (по умолчанию - 0),
указатель на процедуру (с которого начинается выполнение потока),
аргумент с предыдущего потока
записать dwThreadID созданного потока*/
::ResumeThread(hThreads[0]);//запускаем наши потоки
::ResumeThread(hThreads[1]);
::ResumeThread(hThreads[2]);
::ResumeThread(hThreads[3]);
::WaitForMultipleObjects(5, hThreads, TRUE, INFINITE);
::CloseHandle(hThreads[0]);
::CloseHandle(hThreads[1]);
::CloseHandle(hThreads[2]);
::CloseHandle(hThreads[3]);
::CloseHandle(hThreads[4]);
::CloseHandle(g_hMutex);
return 0;
} |
|
0
|