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

类内函数中std::mutex在多线程调用时同步失效问题

类内std::mutex无法实现线程同步的原因分析

问题现象

调用ThreadLessons类的func函数时,输出的Number 1、2、3混乱无序,未达到std::mutex预期的同步效果;但使用全局std::mutex的func函数输出的Number 4、5、6则完全有序。预期通过mutex保护共享资源std::cout,实现线程安全的输出。

相关代码

#include <thread>
#include <iostream>
#include <mutex>

class ThreadLessons {
private:
    std::mutex _threading_mutex_in_class;
public:
    ThreadLessons() {}
    ThreadLessons(const ThreadLessons &tl) {}
    ThreadLessons operator=(const ThreadLessons &tl) {return *this;}
    
    void func(std::string s) {
        std::unique_lock lg(_threading_mutex_in_class);
        std::cout << std::endl;
        for(int i{0}; i<10; i++) {
            std::cout << s << std::endl;
        }
    }
};

std::mutex _threading_mutex;

void func(std::string s) {
    std::unique_lock lg(_threading_mutex);
    std::cout << std::endl;
    for(int i{0}; i<10; i++) {
        std::cout << s << std::endl;
    }
}

int main()
{
    std::cout << "Starting threading of function from another class in same file" << std::endl;
    ThreadLessons t;
    std::thread t1(&ThreadLessons::func, t, "Number 1");
    std::thread t2(&ThreadLessons::func, t, "Number 2");
    std::thread t3(&ThreadLessons::func, t, "Number 3");

    t1.join();
    t2.join();
    t3.join();
    
    std::cout << "Starting threading of function from main" << std::endl;
    std::thread t4(func, "Number 4");
    std::thread t5(func, "Number 5");
    std::thread t6(func, "Number 6");

    t4.join();
    t5.join();
    t6.join();
    
    return 0;
}

运行输出

Starting threading of function from another class in same file

Number 1
Number 1
Number 1
Number 2
Number 2
Number 2


Number 3
Number 3
Number 1Number 2
Number 2
Number 3
Number 3Number 1


Number 2
Number 1Number 3Number 2

Number 2
Number 3
Number 3
Number 1
Number 1
Number 2
Number 1Number 3


Number 2
Number 1
Number 3
Number 3
Starting threading of function from main

Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4

Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5

Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6

问题根源

创建线程时,std::thread t1(&ThreadLessons::func, t, "Number 1")中的t是值传递,std::thread会自动复制这个对象,导致t1、t2、t3各自持有一个独立的ThreadLessons实例。每个实例都拥有自己的_threading_mutex_in_class,相当于每个线程用自己的锁,完全起不到互斥作用,自然无法同步输出。

而全局的_threading_mutex是唯一的,所有线程都争抢这同一个锁,同一时间只有一个线程能操作std::cout,因此输出有序。

修复方案

有两种常用的修复方式:

1. 传递对象引用给线程

创建线程时使用std::ref(t)传递原对象的引用,让三个线程共享同一个ThreadLessons实例,这样它们会使用同一个类内mutex:

std::thread t1(&ThreadLessons::func, std::ref(t), "Number 1");
std::thread t2(&ThreadLessons::func, std::ref(t), "Number 2");
std::thread t3(&ThreadLessons::func, std::ref(t), "Number 3");

2. 将类内mutex声明为static

把_threading_mutex_in_class改成静态成员,这样不管创建多少ThreadLessons对象,所有实例共享同一个mutex:

class ThreadLessons {
private:
    static std::mutex _threading_mutex_in_class; // 声明为static
public:
    // 其他成员函数不变
};

// 必须在类外定义静态成员
std::mutex ThreadLessons::_threading_mutex_in_class;

修改后,类内func的线程就能通过同一个mutex实现互斥,输出效果会和全局mutex的版本一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:45:42