【发布时间】:2021-07-15 13:32:25
【问题描述】:
我有一个许多线程可以访问的std::function 对象。线程可以改变它指向的函数(通过它的拷贝构造函数)并且可以调用它指向的函数。
所以,我的问题是,std::function 对象 本身 线程在哪些方面是安全的?我不是在谈论它指向/调用的函数,我是在谈论 std::function 对象本身。
令人惊讶的是,互联网上只有少数几个网站谈论这个,而且所有(我遇到的)都谈论它指向的功能,不是对象本身。
这些是我读过的主要网站:
Does std::function lock a mutex when calling an internal mutable lambda?
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4348.html
如果你阅读它们,你会发现没有一个在谈论 std::function 对象本身的安全性。
根据this 页面上的第二个答案,STL 库在这些情况下是线程安全的:
-
同时读取同一个对象是可以的
-
不同对象的同时读/写是可以的
基于此,当我设置 std::function 对象指向的函数时,对于这个用例,std::function 对象不是线程安全的。但我问以防万一,因为根据this问题的回答,它有某种内部互斥体。
那么,我怎样才能使它线程安全?一种选择是使用互斥锁,但由于以下示例,这将无法完全发挥作用:
假设我有一个std::function 对象func 和std::mutex m 来保护函数。我锁定 m 并调用该函数(以保护其他线程在调用它指向的函数时不设置 func )并在函数退出时解锁 m 。可以说这个函数调用需要很长时间。这样,当一个线程想要设置 func 时,它会尝试锁定互斥体,但会一直阻塞,直到后一个函数调用退出。在这种情况下我该怎么办?
我想过使用一个指向 std::function 对象的指针。这样,我将使用互斥锁来保护这个指针,当我进行函数调用时,我锁定互斥锁只是为了从指针中检索函数对象。
【问题讨论】:
-
“线程可以改变它指向的函数”——那么它就需要被保护,就像其他不是本能原子的东西一样。 调用它指向的函数与被调用的代码一样是线程安全的;不多也不少。即使你在第一种情况下复制,你仍然需要保护,只要有一个潜在的作家在混合的某个地方。
-
除非某些内容被明确记录为线程安全,否则您必须假设没有线程安全
标签: c++ multithreading stl std