信号量&实现线程同步代码

信号量&实现线程同步代码

  • 信号量
  • 线程同步
  • 示例代码

信号量

信号量(Semaphore)是一种用于多线程编程中的同步工具,用于管理对共享资源的访问。它可以控制同时访问某个资源的线程数量,并提供了对共享资源的互斥访问。
信号量&实现线程同步代码_第1张图片

信号量通常用于解决线程间的互斥和同步问题,其中包括以下两种类型的信号量:

  1. 二进制信号量(Binary Semaphore):也称为互斥信号量(Mutex Semaphore),它只有两种状态:0和1。它用于实现临界区的互斥访问,即同一时间只允许一个线程访问共享资源。典型的例子是互斥锁(Mutex)。

  2. 计数信号量(Counting Semaphore):也称为一般信号量(General Semaphore),它可以有多个状态值。它用于控制多个线程对共享资源的访问数量,可以限制同时访问某个资源的线程数目。典型的例子是生产者-消费者问题中的缓冲区。

常见的信号量操作包括:

  • sem_init:初始化信号量,设置初始值。
  • sem_wait:等待信号量,如果信号量值大于0,则将信号量值减1,继续执行;否则线程阻塞等待。
  • sem_post:释放信号量,将信号量值加1,唤醒等待的线程。
  • sem_destroy:销毁信号量,释放相关资源。

需要注意的是,信号量不仅限于线程间的同步,还可以用于进程间的同步。在多进程编程中,可以使用命名信号量(Named Semaphore)来实现不同进程之间的同步与互斥。

信号量提供了一种有效的方式来协调并发线程对共享资源的访问,避免竞态条件和数据不一致性问题。它是多线程编程中重要的同步机制之一。

线程同步

线程同步是指多个线程之间协调和管理共享资源的访问,以确保线程安全和数据一致性。在线程并发执行时,如果多个线程同时访问共享资源,可能会导致竞态条件(Race Condition)和数据不一致的问题。因此,需要使用适当的同步机制来保证线程间的正确协作。

下面介绍几种常见的线程同步机制:

  1. 互斥锁(Mutex):互斥锁是一种二进制信号量,用于实现对临界区(Critical Section)的互斥访问。一次只允许一个线程进入临界区,其他线程需要等待。常用的函数有pthread_mutex_init(初始化互斥锁)、pthread_mutex_lock(获取互斥锁)、pthread_mutex_unlock(释放互斥锁)、pthread_mutex_destroy(销毁互斥锁)。

  2. 条件变量(Condition Variable):条件变量用于线程间的等待和唤醒机制。它允许线程在某个条件满足时等待,而不是忙等待。常用的函数有pthread_cond_init(初始化条件变量)、pthread_cond_wait(等待条件变量满足)、pthread_cond_signal(唤醒等待线程)、pthread_cond_broadcast(广播唤醒所有等待线程)、pthread_cond_destroy(销毁条件变量)。

  3. 信号量(Semaphore):信号量是一种计数信号量,用于控制多个线程对共享资源的访问数量。它可以限制同时访问某个资源的线程数目。常用的函数有sem_init(初始化信号量)、sem_wait(等待信号量)、sem_post(释放信号量)、sem_destroy(销毁信号量)。

  4. 屏障(Barrier):屏障用于同步多个线程,在达到指定数量的线程之前,线程将被阻塞,等待其他线程到达。当所有线程都到达屏障点后,它们将同时继续执行。常用的函数有pthread_barrier_init(初始化屏障)、pthread_barrier_wait(等待屏障)、pthread_barrier_destroy(销毁屏障)。

这些同步机制可以根据具体需求选择和组合使用,以确保线程安全和数据一致性。线程同步的正确实现可以避免竞态条件和数据不一致性问题,确保多线程程序的正确性。

示例代码

下面是一个使用C语言编写的信号量实现线程同步的示例代码:

#include 
#include 
#include 
#include 

#define NUM_THREADS 3

sem_t semaphore;

void* thread_function(void* thread_id) {
    int id = *(int*)thread_id;
    
    printf("Thread %d: Waiting for semaphore...\n", id);
    sem_wait(&semaphore); // 等待信号量
    
    printf("Thread %d: Semaphore acquired.\n", id);
    
    // 执行一些需要同步的操作
    
    printf("Thread %d: Releasing semaphore.\n", id);
    sem_post(&semaphore); // 释放信号量
    
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    // 初始化信号量
    if (sem_init(&semaphore, 0, 1) == -1) {
        perror("Semaphore initialization failed");
        exit(EXIT_FAILURE);
    }
    
    // 创建线程
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        if (pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]) != 0) {
            perror("Thread creation failed");
            exit(EXIT_FAILURE);
        }
    }
    
    // 等待线程结束
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 销毁信号量
    sem_destroy(&semaphore);

    return 0;
}

在这个示例中,我使用了pthread库和semaphore信号量来实现线程同步。semaphore是一个信号量变量,通过sem_init函数进行初始化,并设置初始值为1。

每个线程通过调用sem_wait函数等待信号量。如果信号量的值大于0,则线程将继续执行;否则,线程将阻塞,直到信号量的值变为大于0为止。

在需要同步的操作执行完毕后,线程调用sem_post函数释放信号量,将信号量的值加1,允许其他线程继续执行。

主函数中创建了多个线程,并等待它们执行完毕。最后,通过sem_destroy函数销毁信号量。

注意:在实际应用中,可能需要更复杂的线程同步机制和更详细的错误处理。此示例仅用于演示基本的信号量使用方法。

你可能感兴趣的:(嵌入式学习,linux,c语言)