linux 互斥锁mutex锁使用示例

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

linux 互斥锁mutex锁使用示例,两个线程操作一个全局变量。


提示:以下是本篇文章正文内容,下面案例可供参考

一、互斥锁mutex是什么?

互斥锁(Mutex,Mutual Exclusion Object的简称)是一种常用的同步机制,用于控制多个线程或进程对共享资源的独占访问。在多线程或多进程编程中,当多个执行单位(如线程)需要访问同一份共享数据时,如果没有适当的同步措施,可能会导致竞态条件(race condition),从而引起程序行为的不确定性。

  1. 互斥锁(Mutex)
  • 适用场景:当需要保护一个共享资源,确保同一时刻只有一个线程可以访问时,互斥锁是首选。
  • 优点:简单易用,支持递归锁,即允许一个线程多次锁定同一个锁而不死锁。
  • 缺点:如果线程被调度器挂起或阻塞,持有锁的线程可能无法及时释放锁,导致其他线程等待。

当一个线程对互斥锁(mutex)加锁后,任何其他试图对该锁加锁的线程都将被阻塞,直到原始持有锁的线程释放锁。
互斥锁用在 同一个进程的线程间 使用
pthread_mutex_init
pthread_mutex_destroy
pthread_mutex_lock
pthread_mutex_trylock
pthread_mutex_unlock

二、代码示例

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

// 定义一个全局变量
int global_counter = 0;

// 创建一个互斥锁
pthread_mutex_t counter_lock;

// 函数用于修改全局变量
void increment_counter() {
    //pthread_mutex_lock(&counter_lock); // 加锁
    int ret = -1;

    while(ret != 0)
    {
    ret = pthread_mutex_trylock(&counter_lock);
    if(0 == ret)
    {
        global_counter++;                  // 修改全局变量
        pthread_mutex_unlock(&counter_lock); // 解锁
    }else if(ret == EBUSY)
    {
        printf("EBUSY\n");
    }else
    {
        printf("pthread_mutex_trylock error ret = %d\n", ret);
    }
    }
}

// 线程函数
void* thread_function(void* arg) {
    int i;
    for (i = 0; i < 10; i++) {
        printf("thread_function enter id = %d, i = %d, global_counter = %d\n", *((int *)arg),i, global_counter);
        increment_counter();
        usleep(1); // 防止第一个线程执行完,第二个线程才执行
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    int i = 1;
    int j = 2;

    // 初始化互斥锁
    pthread_mutex_init(&counter_lock, NULL);

    // 创建两个线程
    pthread_create(&thread1, NULL, thread_function, &i);
    pthread_create(&thread2, NULL, thread_function, &j);

    // 等待两个线程结束
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    // 销毁互斥锁
    pthread_mutex_destroy(&counter_lock);

    // 输出最终的全局变量值
    printf("Final value of the counter is %d\n", global_counter);

    return 0;
}

总结

应用层c,互斥锁的基本使用,代码可以运行。

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 实现的。在加操作中,通过原子操作对计数进行加一,并根据计数判断是否需要将当前线程加入到等待队列中;在解操作中,通过原子操作对计数进行减一,并根据计数判断是否需要唤醒等待队列中的一个线程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值