在Linux系统中,如何确保多线程环境下共享变量的同步与一致性?

Linux多线程共享变量的机制涉及多个方面,包括互斥锁、信号量等同步原语的使用,以及线程间通讯的方法,以下是对这些方面的详细解释和示例:

在Linux系统中,如何确保多线程环境下共享变量的同步与一致性?插图1

一、互斥锁(Mutex)

1. 定义与作用

定义:互斥锁(Mutex)是一种用于保护临界区的同步机制,确保在同一时刻只有一个线程能够访问共享资源。

作用:防止多个线程同时访问共享资源,从而避免数据竞争和不一致性问题。

2. 使用步骤

1、初始化:在使用前需要对互斥锁进行初始化。

   pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

2、加锁:在进入临界区前,线程需要获取互斥锁。

   pthread_mutex_lock(&mutex);

3、访问共享资源:在持有互斥锁的情况下,线程可以安全地访问共享资源。

4、解锁:完成对共享资源的访问后,线程需要释放互斥锁。

在Linux系统中,如何确保多线程环境下共享变量的同步与一致性?插图3

   pthread_mutex_unlock(&mutex);

3. 示例代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int sharedVar = 0; // 共享变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁
void* threadFunc(void* arg) {
    for (int i = 0; i < 100000; ++i) {
        pthread_mutex_lock(&mutex); // 加锁
        sharedVar++; // 访问共享变量
        pthread_mutex_unlock(&mutex); // 解锁
    }
    return NULL;
}
int main() {
    pthread_t t1, t2;
    pthread_create(&t1, NULL, threadFunc, NULL);
    pthread_create(&t2, NULL, threadFunc, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    printf("Final value of sharedVar: %d
", sharedVar);
    return 0;
}

在这个示例中,两个线程通过互斥锁来同步对共享变量sharedVar的访问,确保最终结果是准确的。

二、信号量(Semaphore)

1. 定义与作用

定义:信号量是一种更为灵活的同步机制,可以控制多个线程对共享资源的访问,它不仅可以实现互斥访问,还可以实现资源的计数管理。

作用:通过信号量的等待和通知机制,可以实现复杂的线程同步逻辑。

2. 使用步骤

1、初始化:在使用前需要对信号量进行初始化。

   sem_t semaphore;
   sem_init(&semaphore, 0, initialValue);

2、等待(P操作):线程在需要访问共享资源时,执行等待操作,如果信号量的值大于零,则减一并继续执行;否则,线程将阻塞直到信号量的值大于零。

在Linux系统中,如何确保多线程环境下共享变量的同步与一致性?插图5

   sem_wait(&semaphore);

3、访问共享资源:在持有信号量的情况下,线程可以安全地访问共享资源。

4、释放(V操作):完成对共享资源的访问后,线程需要释放信号量。

   sem_post(&semaphore);

5、销毁:在程序结束时,需要销毁信号量。

   sem_destroy(&semaphore);

3. 示例代码(生产者-消费者问题)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define MAXSIZE 5
int buffer[MAXSIZE];
int in = 0;
int out = 0;
sem_t empty; // 表示空余量的信号量
sem_t full;  // 表示满容量的信号量
pthread_mutex_t mutex; // 用于保护临界区的互斥锁
void put(int value) {
    buffer[in] = value;
    in = (in + 1) % MAXSIZE;
}
int get() {
    int tmp = buffer[out];
    out = (out + 1) % MAXSIZE;
    return tmp;
}
void* producer(void* arg) {
    for (int i = 0; i < 10; i++) {
        sem_wait(&empty); // P操作,检查空余量
        pthread_mutex_lock(&mutex); // 加锁保护临界区
        put(i); // 生产产品
        printf("Produced: %d
", i);
        pthread_mutex_unlock(&mutex); // 解锁
        sem_post(&full); // V操作,增加满容量
        sleep(rand() % 5); // 模拟生产时间
    }
    return NULL;
}
void* consumer(void* arg) {
    for (int i = 0; i < 10; i++) {
        sem_wait(&full); // P操作,检查满容量
        pthread_mutex_lock(&mutex); // 加锁保护临界区
        int tmp = get(); // 消费产品
        printf("Consumed: %d
", tmp);
        pthread_mutex_unlock(&mutex); // 解锁
        sem_post(&empty); // V操作,增加空余量
        sleep(rand() % 5); // 模拟消费时间
    }
    return NULL;
}
int main() {
    pthread_t producerThread, consumerThread;
    sem_init(&empty, 0, MAXSIZE); // 初始化空余量信号量
    sem_init(&full, 0, 0);         // 初始化满容量信号量
    pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
    pthread_create(&producerThread, NULL, producer, NULL);
    pthread_create(&consumerThread, NULL, consumer, NULL);
    pthread_join(producerThread, NULL);
    pthread_join(consumerThread, NULL);
    sem_destroy(&empty); // 销毁信号量
    sem_destroy(&full);  // 销毁信号量
    pthread_mutex_destroy(&mutex); // 销毁互斥锁
    return 0;
}

在这个示例中,生产者和消费者通过信号量和互斥锁来实现对缓冲区的同步访问,生产者在生产产品前会检查空余量(empty),并在生产后增加满容量(full),消费者在消费产品前会检查满容量(full),并在消费后增加空余量(empty),互斥锁用于保护对缓冲区的直接访问,确保在任何时刻只有一个线程能够修改缓冲区的状态。

以上就是关于“linux 多线程共享变量”的问题,朋友们可以点击主页了解更多内容,希望可以够帮助大家!

本文来源于互联网,如若侵权,请联系管理员删除,本文链接:https://www.9969.net/88347.html

小末小末
上一篇 2024年11月1日 16:17
下一篇 2024年11月1日 17:25

相关推荐