创建两个线程,线程1打印奇数,线程2打印偶数,要求按顺序打印1-100。
我们可以使用不同的同步机制来解决这个问题,以下是使用互斥锁、条件变量、信号量和自旋锁的示例。
互斥锁是最常见的同步机制之一,通过锁的机制,确保在任意时刻只有一个线程可以访问共享资源。
#include
#include
// 定义全局变量和互斥锁
int current_number = 1;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 打印奇数的线程函数
void *print_odd(void *arg) {
while (current_number < 100) {
// 获取互斥锁
pthread_mutex_lock(&mutex);
// 打印奇数
if (current_number % 2 != 0) {
printf("Thread-1: %d\n", current_number);
current_number++;
}
// 释放互斥锁
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
// 打印偶数的线程函数
void *print_even(void *arg) {
while (current_number <= 100) {
// 获取互斥锁
pthread_mutex_lock(&mutex);
// 打印偶数
if (current_number % 2 == 0) {
printf("Thread-2: %d\n", current_number);
current_number++;
}
// 释放互斥锁
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main() {
// 定义线程变量
pthread_t thread1, thread2;
// 创建线程
pthread_create(&thread1, NULL, print_odd, NULL);
pthread_create(&thread2, NULL, print_even, NULL);
// 等待线程结束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
条件指示器用于在满足特定条件时通知其他线程。这在需要等待某个条件成立的情况下非常有用。
#include
#include
int current_number = 1;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t odd_condition = PTHREAD_COND_INITIALIZER;
pthread_cond_t even_condition = PTHREAD_COND_INITIALIZER;
void *print_odd(void *arg) {
while (current_number <= 100) {
pthread_mutex_lock(&mutex);
if (current_number % 2 != 0) {
printf("Thread-1: %d\n", current_number);
current_number++;
pthread_cond_signal(&even_condition); // 唤醒等待偶数的线程
} else {
pthread_cond_wait(&odd_condition, &mutex); // 等待偶数的线程唤醒
}
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void *print_even(void *arg) {
while (current_number <= 100) {
pthread_mutex_lock(&mutex);
if (current_number % 2 == 0) {
printf("Thread-2: %d\n", current_number);
current_number++;
pthread_cond_signal(&odd_condition); // 唤醒等待奇数的线程
} else {
pthread_cond_wait(&even_condition, &mutex); // 等待奇数的线程唤醒
}
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, print_odd, NULL);
pthread_create(&thread2, NULL, print_even, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
信号量是一种更为通用的同步机制,可以用于线程间的信号通知和资源控制
#include
#include
#include
sem_t odd_sem, even_sem;
void *print_odd(void *arg) {
for (int i = 1; i <= 100; i += 2) {
sem_wait(&odd_sem); // 等待odd_sem信号量
printf("Thread-1: %d\n", i);
sem_post(&even_sem); // 发送even_sem信号量
}
pthread_exit(NULL);
}
void *print_even(void *arg) {
for (int i = 2; i <= 100; i += 2) {
sem_wait(&even_sem); // 等待even_sem信号量
printf("Thread-2: %d\n", i);
sem_post(&odd_sem); // 发送odd_sem信号量
}
pthread_exit(NULL);
}
int main() {
sem_init(&odd_sem, 0, 1); // 初始值为1
sem_init(&even_sem, 0, 0); // 初始值为0
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, print_odd, NULL);
pthread_create(&thread2, NULL, print_even, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
sem_destroy(&odd_sem);
sem_destroy(&even_sem);
return 0;
}
屏障用于在所有线程都到达某一点之前,阻止它们的执行,然后一起继续执行。
#include
#include
pthread_barrier_t barrier;
void *print_odd(void *arg) {
for (int i = 1; i <= 100; i += 2) {
printf("Thread-1: %d\n", i);
pthread_barrier_wait(&barrier);
// 等待一次,确保奇数线程和偶数线程的交替执行
pthread_barrier_wait(&barrier);
}
pthread_exit(NULL);
}
void *print_even(void *arg) {
for (int i = 2; i <= 100; i += 2) {
pthread_barrier_wait(&barrier);
// 等待一次,确保奇数线程和偶数线程的交替执行
pthread_barrier_wait(&barrier);
printf("Thread-2: %d\n", i);
}
pthread_exit(NULL);
}
int main() {
pthread_t thread1, thread2;
pthread_barrier_init(&barrier, NULL, 2);
pthread_create(&thread1, NULL, print_odd, NULL);
pthread_create(&thread2, NULL, print_even, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_barrier_destroy(&barrier);
return 0;
}
如果不多等待一次会出现顺序交叉
自旋锁是一种忙等待的同步机制,在锁被释放前,线程会一直处于忙等待状态。
#include
#include
typedef struct {
int is_locked;
} spinlock_t;
spinlock_t lock = {0}; // 初始化自旋锁
void spinlock_init(spinlock_t *lock) {
lock->is_locked = 0;
}
void spinlock_lock(spinlock_t *lock) {
while (__sync_lock_test_and_set(&lock->is_locked, 1)) {
// 忙等待,直到锁被释放
// 注意: __sync_lock_test_and_set是一个原子操作
}
}
void spinlock_unlock(spinlock_t *lock) {
__sync_lock_release(&lock->is_locked);
}
int current_number = 1;
void *print_odd(void *arg) {
while (current_number < 100) {
spinlock_lock(&lock);
if (current_number % 2 != 0) {
printf("Thread-1: %d\n", current_number);
current_number++;
}
spinlock_unlock(&lock);
}
pthread_exit(NULL);
}
void *print_even(void *arg) {
while (current_number <= 100) {
spinlock_lock(&lock);
if (current_number % 2 == 0) {
printf("Thread-2: %d\n", current_number);
current_number++;
}
spinlock_unlock(&lock);
}
pthread_exit(NULL);
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, print_odd, NULL);
pthread_create(&thread2, NULL, print_even, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}