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

时间:2019-04-16 15:10:08

标签: c++ c++98

我想知道按值传递事物时可变剪切的工作原理。我会在调用函数之前锁定互斥锁,然后在进入函数后在函数内部解锁吗?使用线程时,按值传递是否更可取?

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。

2 个答案:

答案 0 :(得分:3)

这是在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的返回值和queSizeCheck的参数的副本。最终导致该代码实际上比C ++ 11代码井井有条。从C ++ 17开始,由于强制复制省略,这再次成为更好的解决方案。

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

答案 1 :(得分:0)

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

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

但是。将mutex锁定在一个功能中然后将其解锁在另一个功能中是不明智的。 您应该使用这种方法。

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

您可以使用lock_guard了解RAII的实现方式。