CPUに「もっと」または排他的な権利があるwhileループのような状況がありますか?
まあ、それは定義されていませんが、それは気違いです。
問題を再現できません。睡眠時間を2
と5
秒に減らす(私は永遠に待つ必要がないので)子供は、最初にブロックされなくなります。 (AMD64のDebian 8、Linux 3.16.1-ck1 [BFSスケジューラ、非標準]
あなたのスケジューラは非常に変わった動作をしており、はになるかもしれません。しかし、それはスケジューラの特定の動作に依存することは決して良い考えではないと言われています。常にそれは地獄のように破壊され、非常識だと仮定し - 。あなたのコードが実行の特定の順序を許可する場合、はあり、したがって
(*)それを選択するのに十分な非常識なスケジューラも同期プリミティブ(semaphores
とmutexes
のために使用します。たとえば、共有のバージョンで、異なるプロセスで使用することができます - いくつかのシナリオではpipes
を使用することもできます)。
edit:プロセスを同期させるための2つの例を追加します。
最初のバージョン(AB)を用いpipe
S:そして
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv) {
int i = 10000;
int parent_done[2];
int child_done[2];
char dummy[1] = { 0 };
int pid;
pipe(parent_done);
pipe(child_done);
/* stdio buffering would lead to intermingled output */
setvbuf(stdout, 0, _IONBF, 0);
pid = fork();
if (pid == 0) {
close(parent_done[1]);
close(child_done[0]);
while(i > 50) {
if(i%100==0) {
if (i < 10000) write(child_done[1], dummy, 1);
read(parent_done[0], dummy, 1);
}
printf("Child: %d\n", i);
i--;
}
} else {
close(parent_done[0]);
close(child_done[1]);
while(i < 15000) {
if(i%50==0) {
write(parent_done[1], dummy, 1);
read(child_done[0], dummy, 1);
}
printf("Parent: %d\n", i);
i++;
}
}
exit(EXIT_SUCCESS);
}
同じ用いPOSIXセマフォ(セマフォががを意味するので、私見はるかにクリーンであり、同期のために使用される):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <unistd.h>
struct semaphores
{
sem_t child_done;
sem_t parent_done;
};
int main(int argc, char **argv) {
int i = 10000;
int pid;
/* map shared memory for the semaphores */
struct semaphores *sems = mmap(0, sizeof(*sems), PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS, -1, 0);
/* initialize both semaphores as "shared" and with an initial count
* of 0 */
sem_init(&sems->parent_done, 1, 0);
sem_init(&sems->child_done, 1, 0);
/* stdio buffering would lead to intermingled output */
setvbuf(stdout, 0, _IONBF, 0);
pid = fork();
if (pid == 0) {
while(i > 50) {
if(i%100==0) {
if (i < 10000) sem_post(&sems->child_done);
sem_wait(&sems->parent_done);
}
printf("Child: %d\n", i);
i--;
}
sem_post(&sems->child_done);
} else {
while(i < 15000) {
if(i%50==0) {
sem_post(&sems->parent_done);
sem_wait(&sems->child_done);
}
printf("Parent: %d\n", i);
i++;
}
sem_post(&sems->parent_done);
}
exit(EXIT_SUCCESS);
}
WindowsはセマフォーのAPIが異なります。Semaphore Objects on MSDN
(*) edit2ここにあてはまる:例を作成しているうちに、私はstdio
が眠らずに途中でバッファリングをしていることに気づいた。だからあなたのスケジューラでさえ悪く振る舞いませんが、stdio
の実装では非常にの予期せぬ動作ので、のバッファをフラッシュします。それは当然の野生の推測です。すべてのFILE
ハンドルは、Cライブラリのstdio
部分によってバッファされます。これには、あらかじめ定義されたstdin
,stdout
およびstderr
のハンドルが含まれます。結果として、出力で表示される内容が、異なるスレッドまたはプロセスがその出力を作成した順序を必ずしも反映しているとは限りません。私の例のスニペットのように完全にバッファリングを無効にしない限り、もちろんです。
どのような睡眠(50)? –
誰かがコードをコピー/ペーストしたい場合、sleep(50)をsleep(30)に変更しました。睡眠(50)は私のために長い時間がかかります。私は2番目にそれを編集しています。 – chh