C++ std::function对象本身是线程安全的吗?如果没有,我可以用什么方法使它线程安全?
我有一个C++ std::function对象本身是线程安全的吗?如果没有,我可以用什么方法使它线程安全?,c++,multithreading,stl,std,C++,Multithreading,Stl,Std,我有一个std::function对象,许多线程都可以访问它。线程可以更改它指向的函数(通过它的复制构造函数),并可以调用它指向的函数 所以,我的问题是,std::function对象本身在哪些方面是线程安全的?我说的不是它指向/调用的函数,而是std::function对象本身 令人惊讶的是,互联网上只有少数几个站点讨论这个问题,而所有这些站点(我所遇到的)都讨论它指向的功能,而不是对象本身 以下是我读过的主要网站: 如果您阅读它们,您会发现它们都没有谈到std::function对象本身
std::function
对象,许多线程都可以访问它。线程可以更改它指向的函数(通过它的复制构造函数),并可以调用它指向的函数
所以,我的问题是,std::function
对象本身在哪些方面是线程安全的?我说的不是它指向/调用的函数,而是std::function对象本身
令人惊讶的是,互联网上只有少数几个站点讨论这个问题,而所有这些站点(我所遇到的)都讨论它指向的功能,而不是对象本身
以下是我读过的主要网站:
如果您阅读它们,您会发现它们都没有谈到std::function对象本身的安全性
根据第页的第二个答案,在以下情况下,STL库是线程安全的:
- 同时读取同一对象是正常的
- 可以同时读取/写入不同的对象
std::function
对象指向的函数时,对于这个用例,std::function
对象不是线程安全的。但我只是想以防万一,因为根据问题的答案,它有某种内部互斥
那么,我怎样才能保证线程安全呢?一种选择是使用互斥锁,但由于下面的示例,这种方法无法完全起作用:
假设我有一个std::function
对象func
和std::mutex m
来保护func。我锁定m并调用函数(在调用它指向的函数时保护其他线程不设置func),并在函数退出时解锁m。假设这个函数调用将花费很长时间。这样,当一个线程想要设置func时,它将尝试锁定互斥锁,但会一直阻塞,直到后一个函数调用退出。在这种情况下我能做什么
我曾想过使用一个指向std::function对象的指针。这样,我将使用互斥锁来保护这个指针,当我进行函数调用时,我锁定互斥锁只是为了从指针检索函数对象。函数对象与所有其他对象一样。只有数据,std::函数中没有内置互斥体 如果您想用互斥体保护函数,您自己需要创建一个互斥体,并在与函数交互时使用(将它指向其他对象或调用它)
#包括
#包括
#包括
int main(){
std::mutex函数mutex;
std::函数f=[&functionMutex]{
std::cout一个函数对象和所有其他对象一样。只有数据,并且在std::function中没有内置的互斥体
如果您想用互斥体保护函数,您自己需要创建一个互斥体,并在与函数交互时使用(将它指向其他对象或调用它)
#包括
#包括
#包括
int main(){
std::mutex函数mutex;
std::函数f=[&functionMutex]{
std::cout您可以通过赋值或交换来更改std::function
。很明显,您需要保护对它的访问,就像您分配给任何其他非原子对象一样。您通常不会通过复制构造函数来更改对象,因为复制构造函数会创建新对象
为了保护对std::function
对象的访问,不需要指针
std::function<void()> fun, funCopy, otherFun;
std::mutex mutex;
// thread 1
{
auto s = std::scoped_lock{mutex};
funCopy = fun;
}
funCopy();
// thread 2
{
auto s = std::scoped_lock{mutex};
fun = otherFun;
}
std::函数乐趣、函数复制、其他乐趣;
std::互斥互斥;
//线程1
{
auto s=std::作用域锁定{mutex};
funCopy=乐趣;
}
funCopy();
//线程2
{
auto s=std::作用域锁定{mutex};
乐趣=其他乐趣;
}
您可以通过赋值或交换来更改std::function
。很明显,您需要保护对它的访问,就像您分配给任何其他非原子对象一样。您通常不会通过复制构造函数来更改对象,因为复制构造函数会创建新对象
为了保护对std::function
对象的访问,不需要指针
std::function<void()> fun, funCopy, otherFun;
std::mutex mutex;
// thread 1
{
auto s = std::scoped_lock{mutex};
funCopy = fun;
}
funCopy();
// thread 2
{
auto s = std::scoped_lock{mutex};
fun = otherFun;
}
std::函数乐趣、函数复制、其他乐趣;
std::互斥互斥;
//线程1
{
auto s=std::作用域锁定{mutex};
funCopy=乐趣;
}
funCopy();
//线程2
{
auto s=std::作用域锁定{mutex};
乐趣=其他乐趣;
}
“线程可以更改它指向的函数”-然后,它需要得到保护,就像其他非原子性的东西一样。调用它所指向的函数与调用的代码一样是线程安全的;不多也不少。即使在第一种情况下复制了一个副本,只要混合中有潜在的编写者,你仍然需要保护。除非作为线程安全,您必须假设没有线程安全“线程可以更改它指向的函数”-然后,它需要得到保护,就像其他非原子性的东西一样。调用它所指向的函数与调用的代码一样是线程安全的;不多也不少。即使在第一种情况下复制了一个副本,只要混合中有潜在的编写者,你仍然需要保护。除非作为线程安全,您必须假设没有线程安全