c语言编程笔录

首页 > C语言 > c语言

c语言

c语言 使用锁

更新时间:2023-09-18

前言

C语言是一种通用的、面向过程的编程语言,广泛应用于系统软件开发和嵌入式系统中。在多线程编程中,为了保证线程之间共享数据的正确性和一致性,需要使用锁机制来实现临界区的同步。 锁是一种同步机制,用于控制对共享资源的访问。当一个线程获得锁后,其他线程将被阻塞,直到该线程释放锁。这样可以确保在临界区内只有一个线程执行,从而避免竞态条件和数据损坏。 在C语言中,常用的锁机制包括互斥锁(mutex)和条件变量(condition variable)。互斥锁用于保护临界区,而条件变量用于线程间的通信和同步。下面将详细介绍使用锁的方法和示例代码。

使用互斥锁

互斥锁是一种最基本的锁机制,它提供了一个简单的二进制标志,用于指示临界区是否被锁定。在C语言中,可以使用`pthread_mutex`库来创建互斥锁,具体步骤如下: 1. 定义互斥锁变量:`pthread_mutex_t mutex;` 2. 初始化互斥锁:`pthread_mutex_init(&mutex, NULL);` 3. 在临界区前加锁:`pthread_mutex_lock(&mutex);` 4. 在临界区后解锁:`pthread_mutex_unlock(&mutex);` 5. 销毁互斥锁:`pthread_mutex_destroy(&mutex);` 以下是一个使用互斥锁实现线程同步的示例代码:

#include 
#include 

pthread_mutex_t mutex;
int count = 0;

void* thread_func(void* arg) {
    pthread_mutex_lock(&mutex);
    count++;
    printf("Thread %d: count = %d\n", *((int*)arg), count);
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    int num1 = 1, num2 = 2;
    
    pthread_mutex_init(&mutex, NULL);
    
    pthread_create(&thread1, NULL, thread_func, &num1);
    pthread_create(&thread2, NULL, thread_func, &num2);
    
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    
    pthread_mutex_destroy(&mutex);
    
    return 0;
}
在上述代码中,我们使用`pthread_mutex_lock`函数加锁,`pthread_mutex_unlock`函数解锁,确保在临界区内只有一个线程执行。

使用条件变量

条件变量用于在线程间进行等待和通知操作。在C语言中,可以使用`pthread_cond`库来创建条件变量,具体步骤如下: 1. 定义条件变量和对应的互斥锁变量:`pthread_cond_t cond;`和`pthread_mutex_t mutex;` 2. 初始化条件变量和互斥锁:`pthread_cond_init(&cond, NULL);`和`pthread_mutex_init(&mutex, NULL);` 3. 在等待状态前加锁:`pthread_mutex_lock(&mutex);` 4. 等待条件变量满足:`pthread_cond_wait(&cond, &mutex);` 5. 在等待状态后解锁:`pthread_mutex_unlock(&mutex);` 6. 在满足条件后加锁:`pthread_mutex_lock(&mutex);` 7. 通知等待的线程:`pthread_cond_signal(&cond);`或`pthread_cond_broadcast(&cond);` 8. 在通知状态后解锁:`pthread_mutex_unlock(&mutex);` 9. 销毁条件变量和互斥锁:`pthread_cond_destroy(&cond);`和`pthread_mutex_destroy(&mutex);` 以下是一个使用条件变量实现线程间通信的示例代码:

#include 
#include 

pthread_cond_t cond;
pthread_mutex_t mutex;
int count = 0;

void* thread_func1(void* arg) {
    pthread_mutex_lock(&mutex);
    count++;
    printf("Thread 1: count = %d\n", count);
    
    if (count == 1) {
        pthread_cond_signal(&cond);
    }
    
    pthread_mutex_unlock(&mutex);
    return NULL;
}

void* thread_func2(void* arg) {
    pthread_mutex_lock(&mutex);
    
    while (count < 1) {
        pthread_cond_wait(&cond, &mutex);
    }
    
    count++;
    printf("Thread 2: count = %d\n", count);
    
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    
    pthread_create(&thread1, NULL, thread_func1, NULL);
    pthread_create(&thread2, NULL, thread_func2, NULL);
    
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);
    
    return 0;
}
在上述代码中,我们使用`pthread_cond_wait`函数等待条件变量满足,使用`pthread_cond_signal`函数通知等待的线程。通过条件变量的使用,我们实现了线程间的同步和通信。

总结

本文介绍了在C语言中使用锁机制实现线程同步的方法,包括互斥锁和条件变量。互斥锁用于保护临界区,确保在临界区内只有一个线程执行。条件变量用于在线程间进行等待和通知操作,实现线程间的同步和通信。 在使用锁机制时,需要注意以下几点: 1. 锁的范围应尽量小,减少锁的竞争和线程阻塞的时间。 2. 加锁和解锁的次数应相匹配,确保锁的正确使用。 3. 避免死锁和饥饿问题,即确保所有线程都能获取到所需的锁。 通过合理使用锁机制,可以提高多线程程序的效率和可靠性,确保数据的一致性和正确性。