linux 互斥锁源代码分析
时间: 2023-10-14 12:25:20 浏览: 167
互斥锁的消息队列,很综合的程序源码
Linux 互斥锁主要是通过内核中的 mutex API 实现的。下面是一个简单的互斥锁示例代码:
```
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex;
void *thread_func(void *arg)
{
pthread_mutex_lock(&mutex); // 加锁
printf("Thread %d is in critical section\n", *((int*)arg));
pthread_mutex_unlock(&mutex); // 解锁
return NULL;
}
int main()
{
pthread_t tid[2];
int thread_num[2] = {1, 2};
pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
pthread_create(&tid[0], NULL, thread_func, &thread_num[0]);
pthread_create(&tid[1], NULL, thread_func, &thread_num[1]);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_mutex_destroy(&mutex); // 销毁互斥锁
return 0;
}
```
在该示例中,我们首先使用 `pthread_mutex_init()` 初始化互斥锁并创建两个线程。线程函数 `thread_func()` 中,通过 `pthread_mutex_lock()` 和 `pthread_mutex_unlock()` 来进行锁的加解锁操作。
下面是互斥锁的源代码分析:
互斥锁的数据结构定义如下:
```
typedef struct {
int count;
int owner;
struct futex q;
} mutex_t;
```
其中,`count` 表示锁的计数,`owner` 表示当前持有锁的线程 ID,`q` 表示等待队列。
下面是互斥锁的加锁操作 `mutex_lock()` 的源代码:
```
void mutex_lock(mutex_t *lock)
{
if (atomic_inc_return(&lock->count) == 1) {
lock->owner = current_thread_id();
return;
}
if (lock->owner == current_thread_id())
return;
futex_down(&lock->q, lock->count, current_thread_id());
lock->owner = current_thread_id();
}
```
在该函数中,我们首先通过原子加操作 `atomic_inc_return()` 来将 `lock->count` 加 1,并判断锁是否已经被占用。如果是第一个线程获取锁,那么直接将 `lock->owner` 设置为当前线程 ID 并返回,否则则将当前线程加入到等待队列中并阻塞。
下面是互斥锁的解锁操作 `mutex_unlock()` 的源代码:
```
void mutex_unlock(mutex_t *lock)
{
if (!atomic_dec_return(&lock->count)) {
lock->owner = 0;
futex_up(&lock->q, 1);
}
}
```
在该函数中,我们首先通过原子减操作 `atomic_dec_return()` 将 `lock->count` 减 1,并判断是否为 0。如果为 0,则将 `lock->owner` 设置为 0 并唤醒等待队列中的一个线程。
综上所述,Linux 互斥锁主要是通过内核中的 mutex API 实现的。在加锁操作中,通过原子操作对计数进行加一,并根据计数判断是否需要将当前线程加入到等待队列中;在解锁操作中,通过原子操作对计数进行减一,并根据计数判断是否需要唤醒等待队列中的一个线程。
阅读全文