按值传递时如何应用互斥量?

How to apply mutexes when passing by value?

我想知道按值传递时变量共享是如何工作的。我会在调用函数之前锁定互斥锁,然后在进入函数后在函数内部解锁吗?使用线程时按值传递更可取吗?

Mutex Que_mutex;
queue <char> Que;  //access to this must be done with Que_mutex locked
void queSizeCheck(queue<char> quet);

int main() {
//open new threads, which also manipulate Que
//some other code here, where Que.push, Que.pop and Que.front happens at some points
    Que_mutex.lock();
    queSizeCheck(Que);
}

void queSizeCheck(queue<char> quet) {
    Que_mutex.unlock();
    if (quet.size() < 3) {
        //do something
    }
}

我正在使用 C++98 开发 mbed。

当然可以。您甚至没有在此处传递 mutex。您使用的是相同的 mutex.
即将解锁。

即使你在函数中传递mutex。它仍然会被解锁。

不过。在一个函数中锁定 mutex 而在另一个函数中解锁是不明智的。 你应该使用这样的方法。

mutex.lock()
//... some operations on the data structure
mutex.unlock()

您可以使用 lock_guard 查看 RAII 的实现方式。

这是按值传递在 C++98 中被破坏的原因之一。

因为你想持有锁的时间尽可能短,在 C++11 和 C++14 中我会先复制队列,然后解锁互斥量,然后 移动 复制到函数中(假设 queue 是可移动的)。

int main() {
    std::unique_lock<Mutex> lock(Que_mutex);
    auto copy = Que;
    lock.unlock();
    queSizeCheck(std::move(copy));
}

由于问题被标记为 C++98,我们不能使用移动语义。在这种情况下,我会将复制封装到一个单独的函数中,并依赖于足够聪明的编译器来应用复制省略:

queue<char> queCopy() {
    // lock_guard is C++11 but you can easily write your own C++98 implementation
    std::lock_guard<Mutex> lock(Que_mutex);

    // hope the compiler is smart enough to directly initialize the parameter
    // of queSizeCheck without incurring additional copies
    return Que;
}

int main() {
    queSizeCheck(queCopy());
}

这依赖于编译器省略 queCopy 的 return 值和 queSizeCheck 的参数的副本。最终代码实际上比 C++11 代码组织得更好。从 C++17 开始,由于强制复制省略,这再次成为更好的解决方案。

所有这些都假设 queue 的合理实现,这在问题中没有显示。