質問するログイン新規登録

回答編集履歴

1

コード、実行結果追加

2016/12/23 11:35

投稿

naomi3
naomi3

スコア1105

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 = &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