You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pthreads与mutex锁使用异常:多线程共享资源访问问题求助

多线程修改共享Buffer超次数问题的修复

问题根源

你的代码核心问题在于循环条件的判断没有被互斥锁保护:

  • 当buffer接近NUM_MODIFICATIONS(15)时,多个线程可能同时通过buffer < NUM_MODIFICATIONS的检查,然后依次获取锁执行修改操作,最终导致总修改次数超过15次(比如你遇到的17次)。
  • 添加sleep(1)后,线程调度变得均匀,刚好每个线程执行5次,但这只是巧合,并非正确的同步逻辑,一旦调度变化仍会出现问题。

修复后的代码

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

int buffer = 0;
const int NUM_MODIFICATIONS = 15;
pthread_mutex_t lock;

struct Solution {
    unsigned long TID;
    int mod;
};

void * thread_function() {

    struct Solution *sol = malloc(sizeof *sol);
    sol->TID = (unsigned long) pthread_self();
    sol->mod = 0;

    while(1) {
        pthread_mutex_lock(&lock);
        
        // 先在锁内检查是否还需要修改
        if (buffer >= NUM_MODIFICATIONS) {
            pthread_mutex_unlock(&lock);
            break;
        }
        
        printf("TID: %lu, PID: %d, Buffer: %d\n", sol->TID, getpid(), buffer);
        buffer++; 
        sol->mod++;
        pthread_mutex_unlock(&lock);

        // 可选:保留sleep以模拟线程调度延迟,不影响正确性
        // sleep(1);
    }

    return sol;
}

int main() {

    pthread_t t1, t2, t3;
    pthread_mutex_init(&lock, NULL);

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

    void * out_void1, * out_void2, * out_void3;
    struct Solution *out1, *out2, *out3;

    pthread_join(t1, &out_void1);
    pthread_join(t2, &out_void2);
    pthread_join(t3, &out_void3);

    out1 = out_void1;
    out2 = out_void2;
    out3 = out_void3;

    printf("\nTID %lu worked on the buffer %d times\n", out1->TID, out1->mod);
    printf("TID %lu worked on the buffer %d times\n", out2->TID, out2->mod);
    printf("TID %lu worked on the buffer %d times\n", out3->TID, out3->mod);

    printf("\nTotal buffer accesses: %d\n", out1->mod + out2->mod + out3->mod);

    // 释放动态分配的内存,避免泄漏
    free(out1);
    free(out2);
    free(out3);

    pthread_mutex_destroy(&lock);
    return 0;
}

关键修改点

  1. 将buffer状态检查移入锁内:确保只有持有锁的线程才能判断buffer是否需要修改,避免多个线程同时进入修改流程。
  2. 改用无限循环+锁内退出逻辑:替代原来的外部循环条件,保证判断和修改操作的原子性。
  3. 添加内存释放:主线程中释放线程分配的Solution结构体,避免内存泄漏。

效果验证

修改后,无论是否添加sleep(1),总修改次数都会严格控制在15次,各线程的修改次数会根据系统调度情况自然分配(和作业示例中的5、6、4次类似),完全符合作业要求。

内容的提问来源于stack exchange,提问作者Pablo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:07:08