在c++并发中使用互斥锁

using mutex in c++ concurrency

本文关键字:c++ 并发      更新时间:2023-10-16

尝试用c++理解并发编程的细节。遇到了这段代码,却无法理解其中一行代码。附件是详细信息:

template<typename T>
class threadsafe_stack
{
private:
    std::stack<T> data;
    mutable std::mutex m;
public:
    threadsafe_stack(){}
    threadsafe_stack(const threadsafe_stack& other)
    {
    std::lock_guard<std::mutex> lock(other.m);  
    //////////////////why <1>locking other.m not this->m <2> or locking both
    data=other.data;
    }
    // some other codes
}

这是因为threadsafe_stack类的this实例是第一次被构造,所以你可以确定没有其他人正在访问它的字段,所以它不需要使用this->mutex。但是,此时其他人可能正在使用other实例,因此使用该互斥锁来保护otherdata字段免受并发访问是一个好主意。

也就是说,复制构造函数,你看到的代码,是在基于其他实例的对象构造时调用的,例如:

threadsafe_stack copy_of_stack{ original_stack };

现在,在复制构造函数的执行完成之前,任何人都不能在copy_of_stack实例的上下文中调用方法。

每个threadsafe_stack的互斥锁字段的目的是防止互斥锁所属实例的内容被并发访问。

现在,假设有其他线程在original_stack实例上操作:

while (true)
{
    original_stack.push(123);
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

,其中push方法看起来像这样:

void threadsafe_stack<T>::push(const T& value)
{
    std::lock_guard<std::mutex> lock{ this->m };
    data.push(value);
}

可以看到,每个push操作都保护它自己的 data字段。字段data的同一个实例正在被copy_of_stack实例的复制构造函数访问。使用同一个互斥量使得对data字段的访问是互斥的。换句话说:在data = other.data;中,此时没有其他人可以访问data,但是有人可以访问other.data,这就是为什么我们只锁定一个(other的)互斥锁。