Skip to content

Instantly share code, notes, and snippets.

@nukopy
Created September 21, 2025 17:53
Show Gist options
  • Select an option

  • Save nukopy/da7dbbc2620d72b27994ea48a67ffc8f to your computer and use it in GitHub Desktop.

Select an option

Save nukopy/da7dbbc2620d72b27994ea48a67ffc8f to your computer and use it in GitHub Desktop.
C 言語でのマルチスレッドプログラミングでデータ競合を起こす
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
struct net_device {
unsigned int index;
char name[16];
};
// 問題のあるコード(元の net_device_register風)
int unsafe_register(struct net_device *dev) {
static unsigned int index = 0;
// 危険な箇所:読み取り → 使用 → 更新の間に他のスレッドが割り込む可能性
unsigned int current_index = index; // 読み取り
usleep(1000000); // 意図的な遅延(競合状態を発生させやすくする)
dev->index = current_index; // 使用
index = current_index + 1; // 更新
snprintf(dev->name, sizeof(dev->name), "net%d", dev->index);
printf("Thread registered device: %s\n", dev->name);
return 0;
}
pthread_mutex_t mymutex;
int safe_register(struct net_device *dev) {
pthread_mutex_lock(&mymutex);
static unsigned int index = 0;
// 危険な箇所:読み取り → 使用 → 更新の間に他のスレッドが割り込む可能性
unsigned int current_index = index; // 読み取り
usleep(1000000); // 意図的な遅延(競合状態を発生させやすくする)
dev->index = current_index; // 使用
index = current_index + 1; // 更新
snprintf(dev->name, sizeof(dev->name), "net%d", dev->index);
printf("Thread registered device: %s\n", dev->name);
pthread_mutex_unlock(&mymutex);
return 0;
}
void* thread_function(void* arg) {
int thread_id = *(int*)arg;
struct net_device dev;
printf("Thread %d starting registration\n", thread_id);
unsafe_register(&dev);
printf("Thread %d finished: index=%d, name=%s\n", thread_id, dev.index, dev.name);
return NULL;
}
void* thread_function_safe(void* arg) {
int thread_id = *(int*)arg;
struct net_device dev;
printf("Thread %d starting registration\n", thread_id);
safe_register(&dev);
printf("Thread %d finished: index=%d, name=%s\n", thread_id, dev.index, dev.name);
return NULL;
}
int unsafe_condtion() {
printf("=== マルチスレッドでの競合状態デモ ===\n");
pthread_t threads[5];
int thread_ids[5];
// 5つのスレッドを作成
printf("スレッドを作成中...\n");
for (int i = 0; i < 5; i++) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]);
}
printf("スレッドの作成が完了しました\n");
// すべてのスレッドの終了を待つ
printf("スレッドの終了を待ちます...\n");
for (int i = 0; i < 5; i++) {
pthread_join(threads[i], NULL);
}
printf("DONE!\n");
return 0;
}
int safe_condition() {
printf("=== マルチスレッドでの競合状態デモ(スレッドセーフ版) ===\n");
pthread_t threads[5];
int thread_ids[5];
// 5つのスレッドを作成
printf("スレッドを作成中...\n");
for (int i = 0; i < 5; i++) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL, thread_function_safe, &thread_ids[i]);
}
printf("スレッドの作成が完了しました\n");
// すべてのスレッドの終了を待つ
printf("スレッドの終了を待ちます...\n");
for (int i = 0; i < 5; i++) {
pthread_join(threads[i], NULL);
}
printf("DONE!\n");
return 0;
}
int main() {
unsafe_condtion();
safe_condition();
}
@nukopy
Copy link
Author

nukopy commented Sep 21, 2025

ビルド & 実行

gcc -pthread race_condition_demo.c 
./a.out

出力例

=== マルチスレッドでの競合状態デモ ===
スレッドを作成中...
Thread 1 starting registration
Thread 2 starting registration
Thread 3 starting registration
スレッドの作成が完了しました
スレッドの終了を待ちます...
Thread 0 starting registration
Thread 4 starting registration
Thread registered device: net0
Thread 3 finished: index=0, name=net0
Thread registered device: net0
Thread 2 finished: index=0, name=net0
Thread registered device: net0
Thread 4 finished: index=0, name=net0
Thread registered device: net0
Thread 1 finished: index=0, name=net0
Thread registered device: net0
Thread 0 finished: index=0, name=net0
DONE!
=== マルチスレッドでの競合状態デモ(スレッドセーフ版) ===
スレッドを作成中...
スレッドの作成が完了しました
スレッドの終了を待ちます...
Thread 0 starting registration
Thread 1 starting registration
Thread 2 starting registration
Thread 4 starting registration
Thread 3 starting registration
Thread registered device: net0
Thread 0 finished: index=0, name=net0
Thread registered device: net1
Thread 1 finished: index=1, name=net1
Thread registered device: net2
Thread 2 finished: index=2, name=net2
Thread registered device: net3
Thread 4 finished: index=3, name=net3
Thread registered device: net4
Thread 3 finished: index=4, name=net4
DONE!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment