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++ C++;静态资源的线程安全_C++_Multithreading - Fatal编程技术网

C++ C++;静态资源的线程安全

C++ C++;静态资源的线程安全,c++,multithreading,C++,Multithreading,假设我有以下课程: public class Item { public: CString name; int id; UINT type; bool valid; void invalidate(){ valid = false; } ... } public class itemPool { public: static std::vector<Item*> items ; void invalidateOfType

假设我有以下课程:

public class Item { 
public: 
  CString name;  
  int id;
  UINT type;
  bool valid;  
  void invalidate(){
    valid = false;
  }
  ...
}

public class itemPool { 
public: 
  static std::vector<Item*> items ; 
  void invalidateOfType(UINT type){
    for( auto iter : items )
       if ( iter->type == type )
         iter->invalidate();
  }
 ...
}
公共类项{
公众:
CString名称;
int-id;
UINT型;
布尔有效;
无效{
有效=错误;
}
...
}
公共类项目池{
公众:
静态std::向量项;
无效失效失效类型(UINT类型){
用于(自动iter:项目)
如果(国际热核实验堆->类型==类型)
iter->invalidate();
}
...
}
我可以从不同的线程调用“invalidateOfType(UINT-type)”方法吗?
是否存在“未定义行为”的可能性?换句话说,我可以在多个线程中使用静态资源吗(对该资源进行并行调用)?

静态资源与任何共享资源都没有区别。除非它们的方法是线程安全的,否则不应从多个线程同时调用它们。在您的特定情况下,它归结为
invalidate()
是线程安全的问题。对向量本身进行迭代是线程安全的

(对我来说)这个问题出乎意料地变成了一个非常有趣和有教育意义的问题。以下是需要记住的要点。在解释这些问题时,我将从字面上理解代码。我还将在以下假设下进行操作(OP在一些评论中确实澄清了这一点),即在失效发生时没有代码正在读取

所编写的代码将同时在同一个向量上迭代。因为迭代过程中未修改的向量是线程安全的,所以这部分是线程安全的,不需要进一步讨论

第二个问题是“两个或多个线程是否可以对同一类型的同一类型执行
invalidateOfType
”?如果答案是否定的——每个线程都有自己的类型——那么代码是100%线程安全的,因为相同的对象不会从多个线程访问,因此无需进一步讨论

如果上述问题的答案是“是”,那么我们就有一个难题。实际上,它归结为一个问题:“当两个或多个线程同时将相同的内存位置设置为相同的值时,是否会产生意外的结果?”?准确阅读标准并不能给出一个直接的答案

我可以从不同的线程调用“invalidateOfType(UINT-type)”方法吗

亲爱的上帝,不!在运行
invalidateOfType
函数时,只需从另一个线程触摸该数组,就足以使程序立即崩溃。到处都没有锁


至少你应该锁定(即互斥)对阵列本身的访问。

不,你不能。这可能导致两个线程执行
valid=false在同一时间在同一个
有效的
。当另一个线程正在或可能正在访问某个对象时,不允许在一个线程中修改该对象。(可以肯定的是,检查文档中您正在使用的特定线程模型或库,但大多数都有此规则。)


我会在Windows上考虑这一点,因为每个人都这么做。平台的后续更改不太可能破坏每个人的代码。我不会在POSIX平台上这样做,因为文档很清楚,这是不允许的,而且也不常见。

如果您的问题是,从不同线程同时调用
invalidateOfType()
会导致数据流(一个线程读取另一个线程写入同一对象),那么答案是肯定的

但是您可以使用
std::mutex
std::lock\u-guard
来保护资源,在本例中是
items-vector
,例如:

class itemPool {
public:
   static std::vector<Item*> items;
   static std::mutex         items_mutex;

   void invalidateOfType(UINT type) {
      std::lock_guard< std::mutex > scoped_lock(items_mutex);
      for (auto iter : items)
         if (iter->type = type)
         {
            iter->invalidate();
         }
   }
   ...
}
类项目池{
公众:
静态std::向量项;
静态标准::互斥项\u互斥;
无效失效失效类型(UINT类型){
std::lock\u guard作用域锁定(items\u mutex);
用于(自动iter:项目)
如果(国际热核实验堆->类型=类型)
{
iter->invalidate();
}
}
...
}
如果thread1正在执行
invalidateOfType
,而thread2调用了
invalidateOfType
,那么thread2必须等待thread1离开该函数,并且
项互斥锁解锁


使用跨线程共享的每个资源执行此操作以防止损坏。

如果(iter->type=type)
会给您带来问题。我们讨论的是什么类型的线程?Windows线程?POSIX线程?C++-11线程?简而言之,静态字段在线程安全方面与全局变量相同(尽管初始化是线程安全的;请参阅相关问题)。如您所见,有很多讨论,因此您能否通过添加访问
项的所有方法签名来澄清?是否有任何其他位置的
项目
可能被初始化、更改或访问?@Kenney项目是从主应用程序线程初始化的。此时,没有其他可能访问“项”的线程正在运行。我把“类型”系在一根线上。因此,通常一个线程只能处理一个“类型”的项目。然后,下面的答案似乎都是错误的,并且您的代码是线程安全的;-)你为什么这么说????多个线程可以对同一个向量进行任意多次的迭代。但是在迭代的向量中插入或删除一个元素是不安全的。出于无知,你想投多少就投多少,这不会改变任何事情。通过阅读C++11文档的23.2.2节容器数据竞赛[Container.requirements.dataraces]可以自由地进行自我教育。我认为删除、插入和交换会导致问题。但是为什么迭代和设置一个坏的idead?@SaschaMinor,它不会。因为你在迭代时没有检查互斥体。某个地方可能有人在填充该数组,即使您在互斥锁后锁定该数组,该函数也不会被锁定,并将导致竞争条件。只有在不重新分配的情况下,迭代才是安全的,因为
items