并发下的技术方案——锁


并发下锁的机制详解

介绍了并发下的锁


一、互斥锁 (Mutex)

1.1 工作原理

互斥锁通过阻塞线程实现同步,当线程尝试获取已被占用的锁时,会进入睡眠状态,释放CPU资源,直到锁被释放后被唤醒。

1.2 适用场景

  1. 临界区操作较复杂(如文件IO操作)
  2. 锁持有时间较长
  3. 需要避免CPU空转的场景

1.3 代码示例改进

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_callback(void *arg) {
    int *pcount = (int *)arg;
    for (int i = 0; i < 100000; i++) {
        if (pthread_mutex_lock(&mutex) != 0) {
            perror("mutex lock failed");
            break;
        }
        (*pcount)++;
        pthread_mutex_unlock(&mutex);
        usleep(1);
    }
    return NULL;
}

二、自旋锁 (Spinlock)

2.1 工作原理

采用忙等待机制,线程不断尝试获取锁而不释放CPU,直到成功获取锁。

2.2 适用场景

  • 临界区非常短(<几十条指令)
  • 多核处理器环境
  • 不能睡眠的上下文(如中断处理)

2.3 代码示例

pthread_spinlock_t spinlock;

int main() {
    pthread_spin_init(&spinlock, PTHREAD_PROCESS_SHARED);
    // 线程函数内使用:
    pthread_spin_lock(&spinlock);
    (*pcount)++;
    pthread_spin_unlock(&spinlock);
}

三、原子操作与CAS

3.1 CAS原理深度解析

bool cas(int* ptr, int expect, int update) {
    if (*ptr == expect) {
        *ptr = update;
        return true;
    }
    return false;
}

3.2 ABA问题解决方案

版本号方案:

struct atomic_with_version {
    int value;
    int version;
};

bool cas_version(struct atomic_with_version* ptr, 
                int expect_val, int expect_ver,
                int new_val) {
    if (ptr->value == expect_val && ptr->version == expect_ver) {
        ptr->value = new_val;
        ptr->version++;
        return true;
    }
    return false;
}

四、锁机制对比表

在这里插入图片描述

五、线程池深度解析

5.1 核心组件

  1. 任务队列:使用环形缓冲区实现高效存取
  2. 工作者线程:采用pthread_cond_wait进行任务等待
  3. 动态扩容机制
    当任务数 > 核心线程数时创建新线程
    空闲线程超过keepalive时间后自动回收

5.2 高级特性实现

typedef struct {
    void (*function)(void *);
    void *arg;
} threadpool_task_t;

struct threadpool {
    pthread_mutex_t lock;       // 全局锁
    pthread_cond_t notify;      // 条件变量
    threadpool_task_t *queue;   // 任务队列
    int queue_size;             // 队列容量
    int head;                   // 队列头
    int tail;                   // 队列尾
    int count;                  // 当前任务数
    pthread_t *threads;         // 线程数组
    int thread_count;           // 活动线程数
    int shutdown;               // 关闭标志
};

六、性能优化策略

1. 锁粒度控制:

  • 细粒度锁:对哈希表的不同桶使用独立锁
  • 分段锁:将数据结构划分为多个段独立加锁

2. 无锁编程实践:

// 使用__atomic内置函数实现无锁队列
void enqueue(Node** head, int value) {
    Node* newNode = create_node(value);
    do {
        newNode->next = *head;
    } while (!__atomic_compare_exchange(head, &newNode->next, &newNode, false, 
                                      __ATOMIC_RELAXED, __ATOMIC_RELAXED));
}

3. 缓存友好设计:

  • 避免false sharing:使用__attribute__((aligned(64)))对齐关键变量
  • 热点数据隔离:将频繁访问的数据分配到不同缓存行

七、实战注意事项

1. 死锁预防:

  • 严格按照固定顺序获取多个锁
  • 使用pthread_mutex_trylock()设置超时
  • 采用lock hierarchy验证加锁顺序

2. 性能监控:

# 使用perf分析锁竞争
perf record -e contention:contention_begin -a sleep 10
perf script

3. 调试技巧:

  • 开启CLANG线程安全注解:
void do_work() __attribute__((acquire_capability(mutex))) {
    pthread_mutex_lock(&mutex);
}
  • 使用Helgrind检测数据竞争:
valgrind --tool=helgrind ./your_program

https://github.com/0voice

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值