Linux的同步和异步锁

🔐 Linux中的同步和异步锁

在多线程/多进程编程中,锁 (Lock) 是用于控制访问共享资源的机制,防止数据竞争和一致性问题。Linux 提供了多种锁机制,既包括同步锁也包括异步锁,用于满足不同场景下的并发控制需求。


📌 一、同步锁 (Synchronous Lock)

同步锁要求线程在获取锁时必须等待,直到锁被释放。适用于以下场景:
✅ 线程/进程需按序执行;
✅ 共享资源的访问需确保一致性;
✅ 防止竞态条件;

🔎 常见的同步锁类型

锁类型描述
互斥锁 (Mutex)最常用的同步锁,确保同一时刻仅有一个线程访问共享资源;
信号量 (Semaphore)允许多个线程同时访问指定数量的资源;
读写锁 (Read-Write Lock)提供更高效的读操作,允许多个读线程并行执行;
条件变量 (Condition Variable)配合互斥锁,线程需满足某个条件才能继续执行;
自旋锁 (Spinlock)线程在等待锁时会持续循环检查锁状态,适用于短时间临界区;

🔥 1. 互斥锁 (Mutex) 示例

pthread_mutex 是 Linux 中最常用的互斥锁。

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

pthread_mutex_t lock; // 定义一个互斥锁
int counter = 0;

void* thread_function(void* arg) {
    pthread_mutex_lock(&lock);  // 加锁
    counter++;
    printf("线程 %ld, counter = %d\n", pthread_self(), counter);
    sleep(1);  // 模拟耗时任务
    pthread_mutex_unlock(&lock);  // 解锁
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_mutex_init(&lock, NULL);  // 初始化锁

    pthread_create(&t1, NULL, thread_function, NULL);
    pthread_create(&t2, NULL, thread_function, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    pthread_mutex_destroy(&lock);  // 销毁锁
    return 0;
}

输出示例

线程 139889467115264, counter = 1
线程 139889458722560, counter = 2

🔎 互斥锁可防止多个线程同时修改 counter,确保数据安全。


🔥 2. 信号量 (Semaphore) 示例

信号量用于控制同时访问资源的最大线程数

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

sem_t semaphore;  // 定义信号量

void* thread_function(void* arg) {
    sem_wait(&semaphore);  // 获取信号量
    printf("线程 %ld 正在访问资源\n", pthread_self());
    sleep(2);
    printf("线程 %ld 释放资源\n", pthread_self());
    sem_post(&semaphore);  // 释放信号量
    return NULL;
}

int main() {
    pthread_t threads[5];
    sem_init(&semaphore, 0, 2);  // 信号量初始值为 2(允许最多 2 个线程同时访问)

    for (int i = 0; i < 5; i++) {
        pthread_create(&threads[i], NULL, thread_function, NULL);
    }

    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }

    sem_destroy(&semaphore);  // 销毁信号量
    return 0;
}

输出示例

线程 139889467115264 正在访问资源
线程 139889458722560 正在访问资源
线程 139889467115264 释放资源
线程 139889458722560 释放资源
线程 139889450329856 正在访问资源
...

🔎 信号量确保了同时只有 2 个线程访问共享资源。


🔥 3. 读写锁 (Read-Write Lock) 示例

pthread_rwlock 可提高多读场景下的性能。

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

pthread_rwlock_t rwlock;  // 定义读写锁
int counter = 0;

void* reader(void* arg) {
    pthread_rwlock_rdlock(&rwlock);  // 获取读锁
    printf("读线程 %ld: counter = %d\n", pthread_self(), counter);
    pthread_rwlock_unlock(&rwlock);  // 释放读锁
    return NULL;
}

void* writer(void* arg) {
    pthread_rwlock_wrlock(&rwlock);  // 获取写锁
    counter++;
    printf("写线程 %ld: counter = %d\n", pthread_self(), counter);
    pthread_rwlock_unlock(&rwlock);  // 释放写锁
    return NULL;
}

int main() {
    pthread_t readers[3], writer_thread;

    pthread_rwlock_init(&rwlock, NULL);  // 初始化读写锁

    for (int i = 0; i < 3; i++) {
        pthread_create(&readers[i], NULL, reader, NULL);
    }

    pthread_create(&writer_thread, NULL, writer, NULL);

    for (int i = 0; i < 3; i++) {
        pthread_join(readers[i], NULL);
    }
    pthread_join(writer_thread, NULL);

    pthread_rwlock_destroy(&rwlock);  // 销毁读写锁
    return 0;
}

输出示例

读线程 139889467115264: counter = 0
读线程 139889458722560: counter = 0
写线程 139889450329856: counter = 1

🔎 读锁可并发读取,而写锁是独占的


📌 二、异步锁 (Asynchronous Lock)

异步锁不要求线程/进程等待锁的释放,而是使用回调、通知机制等来处理并发操作。

🔎 常见的异步锁类型

锁类型描述
fcntl 锁非阻塞锁,支持多进程文件锁;
异步 I/O (AIO)通过 io_submit()io_getevents() 等实现;
Epoll/Select/Poll非阻塞 I/O 事件监听;
信号 (Signal)使用 sigaction()kill() 等方法触发异步回调;

🔥 fcntl 异步锁 (非阻塞锁) 示例

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    int fd = open("file.txt", O_WRONLY | O_CREAT, 0666);

    struct flock lock;
    lock.l_type = F_WRLCK; // 写锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0; // 锁住整个文件

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        perror("获取锁失败");
        return 1;
    }

    printf("成功获取锁!\n");
    sleep(5);  // 模拟长时间任务
    lock.l_type = F_UNLCK;
    fcntl(fd, F_SETLK, &lock);  // 释放锁

    printf("释放锁\n");
    close(fd);
    return 0;
}

输出示例

成功获取锁!
释放锁

🔎 fcntl 锁不会阻塞线程,而是立即返回,适用于非阻塞 I/O。


🚀 总结

特点同步锁异步锁
等待机制必须等待锁释放才能继续执行;不需等待,采用回调/事件机制;
使用场景资源竞争频繁,数据一致性要求高;I/O 密集型、异步任务;
性能容易阻塞线程,效率可能较低;更加高效,减少线程阻塞;
常见类型Mutex、Semaphore、读写锁;fcntl 锁、AIO、epoll 等;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值