回答編集履歴
1
コード、実行結果追加
answer
CHANGED
@@ -1,3 +1,230 @@
|
|
1
1
|
mainを実行しているメインスレッドになかなか実行権が渡されないので、 while (sum < count_num) がなかなか処理されないまま、子スレッドが処理し続けている・あるいは既に実行を終了していることが考えられます。スレッドへ実行権を与える・剥奪する処理は、OSに強く依存し、そのOSが独自のスケジューリング・アルゴリズムを用いて、ハードウェア構成も含めたシステム全体の都合によってなされます。したがって、スレッドの実行順序は全く保障されません。「想像通りに」動く方が不思議で、特にシステム負荷が重い場合は複雑な挙動をします。
|
2
2
|
|
3
|
-
よってマルチスレッドプログラミングでは、スケジューリングに依存しない書き方が必要で、どうしても実行順序を決めたいときはセマフォなど「同期オブジェクト」を用いてスレッド同士の「待ち合わせ」を行うことが通例です。
|
3
|
+
よってマルチスレッドプログラミングでは、スケジューリングに依存しない書き方が必要で、どうしても実行順序を決めたいときはセマフォなど「同期オブジェクト」を用いてスレッド同士の「待ち合わせ」を行うことが通例です。
|
4
|
+
|
5
|
+
追加
|
6
|
+
|
7
|
+
セマフォ2つを使った同期を示します。
|
8
|
+
そこそこまともに動きます。
|
9
|
+
```C
|
10
|
+
#include <stdio.h>
|
11
|
+
#include <time.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <string.h>
|
14
|
+
#include <pthread.h>
|
15
|
+
#include <semaphore.h>
|
16
|
+
|
17
|
+
struct ThreadArgs
|
18
|
+
{
|
19
|
+
int *count_num;
|
20
|
+
int *n;
|
21
|
+
int *sum;
|
22
|
+
int thread_id;
|
23
|
+
sem_t* sem4n;
|
24
|
+
sem_t* sem4sum;
|
25
|
+
};
|
26
|
+
|
27
|
+
void *thread_func(void *threadArgs);
|
28
|
+
|
29
|
+
void *thread_func(void *threadArgs) {
|
30
|
+
int i, thread_id;
|
31
|
+
int *n, *count_num, *sum;
|
32
|
+
sem_t* sem4n;
|
33
|
+
sem_t* sem4sum;
|
34
|
+
|
35
|
+
pthread_detach(pthread_self());
|
36
|
+
|
37
|
+
struct ThreadArgs *args = (struct ThreadArgs *) threadArgs;
|
38
|
+
|
39
|
+
n = args -> n;
|
40
|
+
sum = args -> sum;
|
41
|
+
count_num = args -> count_num;
|
42
|
+
thread_id = args -> thread_id;
|
43
|
+
sem4n = args -> sem4n;
|
44
|
+
sem4sum = args -> sem4sum;
|
45
|
+
|
46
|
+
free(threadArgs);
|
47
|
+
|
48
|
+
while ( *sum < *count_num) {
|
49
|
+
(*n)++;
|
50
|
+
printf("Thread%d %d\n", thread_id, *n);
|
51
|
+
|
52
|
+
/* 共有データ*nを使用したので、セマフォの加算 */
|
53
|
+
sem_post(sem4n);
|
54
|
+
|
55
|
+
for (i = 0; i < 50000000; i++) {}
|
56
|
+
|
57
|
+
/* 共有データ*sum, *count_numが使えるようになるまで、セマフォの値によるブロック */
|
58
|
+
sem_wait(sem4sum);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
int main(int argc, char *argv[])
|
63
|
+
{
|
64
|
+
int i, j, *n, *top, count_num, thread_num, sum;
|
65
|
+
clock_t time1, time0;
|
66
|
+
double diff;
|
67
|
+
struct ThreadArgs *threadArgs;
|
68
|
+
pthread_t mythread;
|
69
|
+
int thread_id;
|
70
|
+
static sem_t sem4n;
|
71
|
+
static sem_t sem4sum;
|
72
|
+
|
73
|
+
if (argc != 3) {
|
74
|
+
exit(1);
|
75
|
+
}
|
76
|
+
|
77
|
+
count_num = atoi(argv[1]);
|
78
|
+
thread_num = atoi(argv[2]);
|
79
|
+
|
80
|
+
printf("begin %d %d\n", count_num, thread_num);
|
81
|
+
|
82
|
+
n = (int *)malloc(sizeof(int) * thread_num);
|
83
|
+
|
84
|
+
/* セマフォの初期化 */
|
85
|
+
if (sem_init( &sem4n, 0, 0) != 0) {
|
86
|
+
fprintf(stderr, "sem_init() failed\n");
|
87
|
+
exit(1);
|
88
|
+
}
|
89
|
+
if (sem_init( &sem4sum, 0, 0) != 0) {
|
90
|
+
fprintf(stderr, "sem_init() failed\n");
|
91
|
+
exit(1);
|
92
|
+
}
|
93
|
+
|
94
|
+
top = n;
|
95
|
+
|
96
|
+
for (i = 0, n = top; i < thread_num; i++, n++) {
|
97
|
+
*n = 0;
|
98
|
+
}
|
99
|
+
|
100
|
+
sum = 0;
|
101
|
+
|
102
|
+
time0 = clock();
|
103
|
+
|
104
|
+
thread_id = 0;
|
105
|
+
|
106
|
+
for (i = 0, n = top; i < thread_num; i++, n++) {
|
107
|
+
if((threadArgs = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs))) == NULL){
|
108
|
+
fprintf(stderr, "malloc failed?n"), exit(1);
|
109
|
+
}
|
110
|
+
|
111
|
+
threadArgs -> count_num = &count_num;
|
112
|
+
threadArgs -> n = n;
|
113
|
+
threadArgs -> sum = ∑
|
114
|
+
threadArgs -> thread_id = thread_id;
|
115
|
+
threadArgs -> sem4n = &sem4n;
|
116
|
+
threadArgs -> sem4sum = &sem4sum;
|
117
|
+
|
118
|
+
if(pthread_create(&mythread, NULL, thread_func, (void *) threadArgs) != 0){
|
119
|
+
fprintf(stderr, "pthread_create() failed\n"), exit(1);
|
120
|
+
}
|
121
|
+
|
122
|
+
thread_id++;
|
123
|
+
}
|
124
|
+
|
125
|
+
while (sum < count_num) {
|
126
|
+
for (i = 0, sum = 0, n = top; i < thread_num; i++, n++) {
|
127
|
+
/* 共有データ*nが使えるようになるまで、セマフォの値によるブロック */
|
128
|
+
sem_wait(&sem4n);
|
129
|
+
sum += *n;
|
130
|
+
|
131
|
+
/* 共有データsum, count_numを使用したので、セマフォの加算 */
|
132
|
+
sem_post(&sem4sum);
|
133
|
+
}
|
134
|
+
//printf("%d %d\n", sum, count_num);
|
135
|
+
}
|
136
|
+
|
137
|
+
/* セマフォの削除 */
|
138
|
+
sem_destroy(&sem4n);
|
139
|
+
sem_destroy(&sem4sum);
|
140
|
+
|
141
|
+
printf("sum %d\n", sum);
|
142
|
+
|
143
|
+
time1 = clock();
|
144
|
+
|
145
|
+
diff =(double)(time1 - time0) / CLOCKS_PER_SEC;
|
146
|
+
|
147
|
+
printf("%.3f[sec]\n", diff);
|
148
|
+
|
149
|
+
return 0;
|
150
|
+
}
|
151
|
+
```
|
152
|
+
> begin 1000 20
|
153
|
+
Thread0 1
|
154
|
+
Thread1 1
|
155
|
+
Thread2 1
|
156
|
+
Thread3 1
|
157
|
+
Thread4 1
|
158
|
+
Thread5 1
|
159
|
+
Thread6 1
|
160
|
+
Thread7 1
|
161
|
+
Thread8 1
|
162
|
+
Thread9 1
|
163
|
+
Thread10 1
|
164
|
+
Thread11 1
|
165
|
+
Thread12 1
|
166
|
+
Thread13 1
|
167
|
+
Thread14 1
|
168
|
+
Thread15 1
|
169
|
+
Thread16 1
|
170
|
+
Thread17 1
|
171
|
+
Thread18 1
|
172
|
+
Thread19 1
|
173
|
+
Thread0 2
|
174
|
+
Thread2 2
|
175
|
+
Thread5 2
|
176
|
+
Thread1 2
|
177
|
+
Thread3 2
|
178
|
+
Thread6 2
|
179
|
+
Thread4 2
|
180
|
+
Thread7 2
|
181
|
+
Thread9 2
|
182
|
+
Thread8 2
|
183
|
+
Thread10 2
|
184
|
+
Thread11 2
|
185
|
+
Thread12 2
|
186
|
+
Thread14 2
|
187
|
+
Thread13 2
|
188
|
+
Thread15 2
|
189
|
+
Thread16 2
|
190
|
+
Thread17 2
|
191
|
+
Thread18 2
|
192
|
+
Thread2 3
|
193
|
+
Thread6 3
|
194
|
+
Thread10 3
|
195
|
+
Thread5 3
|
196
|
+
Thread0 3
|
197
|
+
===中略===
|
198
|
+
Thread5 61
|
199
|
+
Thread1 61
|
200
|
+
Thread9 61
|
201
|
+
Thread17 40
|
202
|
+
Thread13 61
|
203
|
+
Thread0 52
|
204
|
+
Thread4 52
|
205
|
+
Thread8 52
|
206
|
+
Thread12 52
|
207
|
+
Thread2 54
|
208
|
+
Thread16 52
|
209
|
+
Thread18 51
|
210
|
+
Thread6 54
|
211
|
+
Thread5 62
|
212
|
+
Thread10 54
|
213
|
+
Thread1 62
|
214
|
+
Thread14 54
|
215
|
+
Thread9 62
|
216
|
+
Thread13 62
|
217
|
+
Thread19 40
|
218
|
+
Thread0 53
|
219
|
+
Thread3 41
|
220
|
+
Thread4 53
|
221
|
+
Thread7 41
|
222
|
+
Thread8 53
|
223
|
+
sum 1010
|
224
|
+
128.482[sec]
|
225
|
+
|
226
|
+
環境
|
227
|
+
Windows 7 Professional SP1
|
228
|
+
Intel Core i5 750
|
229
|
+
Cygwin64
|
230
|
+
GCC 5.4.0
|