MST

星途 面试题库

面试题:C++ 友元函数安全性与多线程场景

在多线程环境下,使用 C++ 类友元函数会带来哪些额外的安全性挑战?例如,当多个线程同时调用友元函数访问类的共享成员时。假设你有一个多线程程序,其中类 `B` 有一个友元函数 `friendThreadFunc`,该函数会修改类 `B` 的某个共享数据成员,描述如何通过同步机制(如互斥锁、条件变量等)来确保该友元函数在多线程环境下的安全使用,并给出相应的代码示例。
37.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

安全性挑战

  1. 数据竞争:多个线程同时调用友元函数访问和修改类的共享成员时,可能导致数据竞争,最终结果具有不确定性,可能出现错误的计算结果或程序崩溃。
  2. 内存一致性:不同线程对共享数据的访问顺序可能不一致,导致程序出现难以调试的逻辑错误。

同步机制实现安全使用

  1. 使用互斥锁: 互斥锁(std::mutex)可以保证在同一时间只有一个线程能够进入临界区,访问共享数据。
#include <iostream>
#include <mutex>
#include <thread>

class B {
    int sharedData;
    std::mutex mtx;
public:
    B() : sharedData(0) {}
    friend void friendThreadFunc(B* obj);
};

void friendThreadFunc(B* obj) {
    // 锁定互斥锁
    std::lock_guard<std::mutex> lock(obj->mtx);
    // 访问和修改共享数据
    obj->sharedData++;
    std::cout << "Thread modified sharedData to: " << obj->sharedData << std::endl;
}

int main() {
    B b;
    std::thread t1(friendThreadFunc, &b);
    std::thread t2(friendThreadFunc, &b);

    t1.join();
    t2.join();

    return 0;
}
  1. 使用条件变量: 条件变量(std::condition_variable)通常与互斥锁配合使用,用于线程间的同步。当某个条件满足时,通知等待的线程。但在简单的修改共享数据场景下,条件变量不是必需的。如果在友元函数中需要根据共享数据的某个条件进行等待,可使用如下方式:
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>

class B {
    int sharedData;
    std::mutex mtx;
    std::condition_variable cv;
    bool ready = false;
public:
    B() : sharedData(0) {}
    friend void friendThreadFunc(B* obj);
};

void friendThreadFunc(B* obj) {
    std::unique_lock<std::mutex> lock(obj->mtx);
    // 等待条件满足
    obj->cv.wait(lock, [&obj] { return obj->ready; });
    // 访问和修改共享数据
    obj->sharedData++;
    std::cout << "Thread modified sharedData to: " << obj->sharedData << std::endl;
}

int main() {
    B b;
    std::thread t1(friendThreadFunc, &b);

    // 模拟一些工作
    std::this_thread::sleep_for(std::chrono::seconds(2));

    {
        std::lock_guard<std::mutex> lock(b.mtx);
        b.ready = true;
    }
    b.cv.notify_one();

    t1.join();

    return 0;
}

上述代码中,std::lock_guard 构造时自动锁定互斥锁,析构时自动解锁,确保临界区代码的安全执行。std::unique_lock 与条件变量配合使用,等待条件满足时才执行后续操作。