按值传递时如何应用互斥量?
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
的合理实现,这在问题中没有显示。
我想知道按值传递时变量共享是如何工作的。我会在调用函数之前锁定互斥锁,然后在进入函数后在函数内部解锁吗?使用线程时按值传递更可取吗?
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
的合理实现,这在问题中没有显示。