笔试编程题---多线程并发

按顺序打印1-100的奇偶数(基于C语言)

问题描述

创建两个线程,线程1打印奇数,线程2打印偶数,要求按顺序打印1-100。

解决方案

我们可以使用不同的同步机制来解决这个问题,以下是使用互斥锁、条件变量、信号量和自旋锁的示例。

互斥锁

互斥锁是最常见的同步机制之一,通过锁的机制,确保在任意时刻只有一个线程可以访问共享资源。

#include <stdio.h>
#include <pthread.h>

// 定义全局变量和互斥锁
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 <stdio.h>
#include <pthread.h>

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 <stdio.h>
#include <pthread.h>
#include <semaphore.h>

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 <stdio.h>
#include <pthread.h>

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 <stdio.h>
#include <pthread.h>

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;
}
  • 22
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值