Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::function对象本身是线程安全的吗?如果没有,我可以用什么方法使它线程安全?_C++_Multithreading_Stl_Std - Fatal编程技术网

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};
乐趣=其他乐趣;
}

“线程可以更改它指向的函数”-然后,它需要得到保护,就像其他非原子性的东西一样。调用它所指向的函数与调用的代码一样是线程安全的;不多也不少。即使在第一种情况下复制了一个副本,只要混合中有潜在的编写者,你仍然需要保护。除非作为线程安全,您必须假设没有线程安全“线程可以更改它指向的函数”-然后,它需要得到保护,就像其他非原子性的东西一样。调用它所指向的函数与调用的代码一样是线程安全的;不多也不少。即使在第一种情况下复制了一个副本,只要混合中有潜在的编写者,你仍然需要保护。除非作为线程安全,您必须假设没有线程安全