Linux中的互斥锁和条件变量

互斥锁和条件变量都是进程同步机制,通常,互斥锁是用来对资源加锁,条件变量用来等待资源,主要包括两个动作:

  • 一个线程等待"条件变量的条件成立"而挂起
  • 另一个线程使"条件成立"(给出条件成立信号)

由于是多线程,为了防止竞争,所以条件量一般和锁一起使用。

目录

1.互斥锁

1.1初始化pthread_mutex_init()

1.2加锁pthread_mutex_lock()

1.3解锁pthread_mutex_unlock()

1.4销毁pthread_mutex_destroy() 

1.5互斥锁完整实例

2.条件变量

2.1初始化pthread_cond_init()

2.2销毁pthread_cond_destroy() 

2.3唤醒pthread_cond_signal()

2.4唤醒所有pthread_cond_broadcast()

2.5等待pthread_cond_timedwait() 

2.6条件变量完整实例


1.互斥锁

互斥锁是一种同步机制,用于确保同一时间只有一个线程可以访问共享资源。在 C 语言中,互斥锁可以通过 pthread_mutex_t 类型来表示,并可以通过 pthread_mutex_init() 函数来初始化。

1.1初始化pthread_mutex_init()

pthread_mutex_init() 函数的原型如下:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

其中,mutex 是要初始化的互斥锁,attr 是互斥锁属性。pthread_mutex_init() 函数的返回值如下:

0:成功

EAGAIN:系统资源不足

EINVAL:mutex 或 attr 为 NULL

EBUSY:mutex 已被初始化

pthread_mutex_init() 函数的用法如下:

pthread_mutex_t mutex;

pthread_mutex_init(&mutex, NULL);

在上面的代码中,首先定义了一个互斥锁 mutex。然后,使用 pthread_mutex_init() 函数初始化互斥锁。

1.2加锁pthread_mutex_lock()

pthread_mutex_lock() 函数用于锁定互斥锁。当一个线程试图锁定一个已经被锁定的互斥锁时,该线程将被阻塞,直到互斥锁被解锁。 pthread_mutex_lock() 函数的原型如下:

int pthread_mutex_lock(pthread_mutex_t *mutex);

其中,mutex 是要锁定的互斥锁。pthread_mutex_lock() 函数的返回值如下:

0:成功

EDEADLK:线程试图锁定自己已经持有的互斥锁

EINVAL:mutex 为 NULL

pthread_mutex_lock() 函数的用法如下:

pthread_mutex_lock(&mutex);

在上面的代码中,使用 pthread_mutex_lock() 函数锁定互斥锁 mutex。

1.3解锁pthread_mutex_unlock()

pthread_mutex_unlock() 函数用于解锁互斥锁。当一个线程解锁一个互斥锁时,该互斥锁将被释放,并且任何被阻塞的线程都可以继续执行。 pthread_mutex_unlock() 函数的原型如下:

int pthread_mutex_unlock(pthread_mutex_t *mutex);

其中,mutex 是要解锁的互斥锁。 pthread_mutex_unlock() 函数的返回值如下:

0:成功

EINVAL:mutex 为 NULL

pthread_mutex_unlock() 函数的用法如下:

pthread_mutex_unlock(&mutex);

在上面的代码中,使用 pthread_mutex_unlock() 函数解锁互斥锁 mutex。

1.4销毁pthread_mutex_destroy() 

pthread_mutex_destroy() 函数用于销毁互斥锁。当一个互斥锁不再需要时,应该使用 pthread_mutex_destroy() 函数来销毁它。 pthread_mutex_destroy() 函数的原型如下:

int pthread_mutex_destroy(pthread_mutex_t *mutex);

其中,mutex 是要销毁的互斥锁。 pthread_mutex_destroy() 函数的返回值如下:

0:成功

EINVAL:mutex 为 NULL

pthread_mutex_destroy() 函数的用法如下:

pthread_mutex_destroy(&mutex);

在上面的代码中,使用 pthread_mutex_destroy() 函数销毁互斥锁 mutex。

1.5互斥锁完整实例

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

pthread_mutex_t mutex;

void *thread_function(void *arg) {
  pthread_mutex_lock(&mutex);

  printf("Thread %ld has locked the mutex\n", pthread_self());

  // 访问共享资源

  printf("Thread %ld has unlocked the mutex\n", pthread_self());

  pthread_mutex_unlock(&mutex);

  return NULL;
}

int main() {
  pthread_t thread1, thread2;

  pthread_mutex_init(&mutex, NULL);

  pthread_create(&thread1, NULL, thread_function, NULL);
  pthread_create(&thread2, NULL, thread_function, NULL);

  pthread_join(thread1, NULL);
  pthread_join(thread2, NULL);

  pthread_mutex_destroy(&mutex);

  return 0;
}

在这个例子中,创建了一个互斥锁 mutex,并使用 pthread_mutex_init() 函数初始化它。然后,创建了两个线程,并使用 pthread_mutex_lock() 函数锁定互斥锁,然后访问共享资源。在访问共享资源之前,打印一条消息,表明线程已经锁定了互斥锁。在访问共享资源之后,打印一条消息,表明线程已经解锁了互斥锁。最后,使用 pthread_mutex_unlock() 函数解锁互斥锁,并使用 pthread_mutex_destroy() 函数销毁互斥锁。

2.条件变量

条件变量是一种同步机制,用于等待某个条件的发生。在 C 语言中,条件变量可以通过 pthread_cond_t 类型来表示,并可以通过 pthread_cond_init() 函数来初始化。

2.1初始化pthread_cond_init()

pthread_cond_init() 函数的原型如下:

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

其中,cond 是要初始化的条件变量,attr 是条件变量属性。 pthread_cond_init() 函数的返回值如下:

0:成功

EAGAIN:系统资源不足

EINVAL:cond 或 attr 为 NULL

EBUSY:cond 已被初始化

pthread_cond_init() 函数的用法如下:

pthread_cond_t cond;

pthread_cond_init(&cond, NULL);

在上面的代码中,首先定义了一个条件变量 cond。然后,我们使用 pthread_cond_init() 函数初始化条件变量。

2.2销毁pthread_cond_destroy() 

pthread_cond_destroy() 函数用于销毁条件变量。当一个条件变量不再需要时,应该使用 pthread_cond_destroy() 函数来销毁它。 pthread_cond_destroy() 函数的原型如下:

int pthread_cond_destroy(pthread_cond_t *cond);

其中,cond 是要销毁的条件变量。 pthread_cond_destroy() 函数的返回值如下:

0:成功

EINVAL:cond 为 NULL

pthread_cond_destroy() 函数的用法如下:

pthread_cond_destroy(&cond);

在上面的代码中,使用 pthread_cond_destroy() 函数销毁条件变量 cond。

2.3唤醒pthread_cond_signal()

pthread_cond_signal() 函数用于唤醒一个正在等待条件变量的线程。当一个线程调用 pthread_cond_signal() 函数时,该线程将被唤醒,并且可以继续执行。 pthread_cond_signal() 函数的原型如下:

int pthread_cond_signal(pthread_cond_t *cond);

其中,cond 是要唤醒的条件变量。 pthread_cond_signal() 函数的返回值如下:

 0:成功

EINVAL:cond 为 NULL

pthread_cond_signal() 函数的用法如下:

pthread_cond_signal(&cond);

在上面的代码中,我们使用 pthread_cond_signal() 函数唤醒条件变量 cond。

2.4唤醒所有pthread_cond_broadcast()

pthread_cond_broadcast() 函数用于唤醒所有正在等待条件变量的线程。当一个线程调用 pthread_cond_broadcast() 函数时,所有正在等待该条件变量的线程将被唤醒,并且可以继续执行。 pthread_cond_broadcast() 函数的原型如下:

int pthread_cond_broadcast(pthread_cond_t *cond);

其中,cond 是要唤醒的条件变量。 pthread_cond_broadcast() 函数的返回值如下:

0:成功

EINVAL:cond 为 NULL

pthread_cond_broadcast() 函数的用法如下:

pthread_cond_broadcast(&cond);

在上面的代码中,我们使用 pthread_cond_broadcast() 函数唤醒条件变量 cond。

2.5等待pthread_cond_timedwait() 

pthread_cond_timedwait() 函数用于等待条件变量的发生。当一个线程调用 pthread_cond_timedwait() 函数时,该线程将被阻塞,直到条件变量发生或超时。 pthread_cond_timedwait() 函数的原型如下:

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

其中,cond 是要等待的条件变量,mutex 是要锁定的互斥锁,abstime 是超时时间。 pthread_cond_timedwait() 函数的返回值如下:

0:成功

ETIMEDOUT:超时

EINVAL:cond 或 mutex 为 NULL

EDEADLK:线程试图锁定自己已经持有的互斥锁

pthread_cond_timedwait() 函数的用法如下:

pthread_cond_timedwait(&cond, &mutex, &abstime);

在上面的代码中,我们使用 pthread_cond_timedwait() 函数等待条件变量 cond 的发生。

2.6条件变量完整实例

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

#define NUM_THREADS 2

int count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;

void* thread_func(void* thread_id) {
    int tid = *((int*)thread_id);
    
    pthread_mutex_lock(&mutex);
    
    while (count < tid) {
        pthread_cond_wait(&cond, &mutex);
    }
    
    printf("Thread %d: Hello, World!\n", tid);
    
    count++;
    
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
    
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];
    
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        pthread_create(&threads[i], NULL, thread_func, (void*)&thread_ids[i]);
    }
    
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    
    return 0;
}

在这个例子中,我们创建了两个线程,并使用条件变量和互斥锁来实现进程同步。每个线程首先会获取互斥锁,然后进入一个循环,只有当count的值小于线程的ID时,线程才会等待条件变量的信号。一旦收到信号,线程会打印一条消息,然后增加count的值,并通过条件变量的广播通知其他线程。最后,我们使用pthread_join等待所有线程执行完毕,并清理互斥锁和条件变量。

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值