【问题标题】:Class with no blocking methodes with multithreading没有多线程阻塞方法的类
【发布时间】:2022-01-17 15:59:18
【问题描述】:

我正在编写一个应该使用多线程功能的类。 目标是我没有任何来自外部的阻塞方法,尽管我在类中使用了具有阻塞功能的库。 我想在他们自己的线程中运行它们。 不幸的是,我遇到了内存故障(核心转储)错误。

在c ++ 11中实现这样的最佳实践是什么?为什么会出现错误,我怎样才能为我想提前在线程中调用的函数指定内存?

我的班级

.. 
class foo {

  void startUp();

  foo();
  ~foo();
  
  std::thread foo_worker;
  int retValue;

};

void foo::startUp() {
  int retValue = 0;

  std::thread t([this] () {
  retValue = blocking_lib_func();
});

foo_worker = std::move(t);

}

foo::~foo() {
  ....
  foo_worker.join();
}

我的主要

int main() 

  foo test();
  test.statUp()
}

【问题讨论】:

  • 您的问题太含糊,无法回答,您不能声称自己的问题没有阻塞,然后在代码中的某个线程上join。建议你看看std::async 或更正经的 IPC 库。
  • 你为什么在这几行中使用这么多的动态内存分配?另外,您认为通过使成员volatile 来做什么?这些都是不良编程习惯的指标,很容易导致问题发生
  • 好的,是的,应该将 .join() 移入析构函数。我使工作线程不稳定,因为该线程正在控制一个 gui 框架,以使 ist “更快”
  • 你不是在创建线程 volatile 你是在创建指向线程 volatile 的指针——这与性能完全无关
  • volatile - "...这使得 volatile 对象适合与信号处理程序通信,但不适用于另一个执行线程..." 见en.cppreference.com/w/cpp/language/cv

标签: c++ multithreading class c++11


【解决方案1】:

与您的线程关联的 lambda 正在捕获对本地堆栈变量的引用。当startUp 返回时,线程将继续运行,但retValue 的地址现在不受限制,包括线程。该线程将通过尝试将某些内容分配给对retValue 的引用来创建未定义的行为。这很可能是您描述的崩溃的根源。或者更糟的是,主线程上的堆栈损坏会以其他方式损坏您的程序。

解决方案很简单。首先,将retValue 设为类的成员变量。当我们这样做时,没有理由让 foo_worker 成为一个指针。

class foo {
public:
  void startUp();

  foo();
  ~foo();

private:      
  std::thread foo_worker;
  int retValue;

};

那么你的startUp 代码可以是这个。我们可以使用std::move将线程从本地的t线程变量移动到类实例的成员变量中。

void foo::startUp() {

  std::thread t([this] () {
      retValue = blocking_lib_func(); // assign to the member variable of foo
  });
  foo_worker = std::move(t);
}

然后你的析构函数可以调用 join 如下:

foo::~foo() {
  ....
  foo_worker.join();
}

正如 cmets 中的其他人所指出的,volatile 没有用处。当使用适当的线程和锁定语义时,它大多被弃用为关键字。

【讨论】:

  • 好的,感谢您的精彩解释:) 我删除了这里的所有易失性,还将变量 retValue 设为类成员,并将线程执行为正常声明。但仍然是同样的错误.. :(
  • 我的问题是阻塞函数一执行就出现错误(内存故障(核心转储))。 .
  • 我认为问题一定出在blocking_lib_func() 的作用上。如果从非主线程调用,那里的 gui 操作可能不起作用。
  • @zombieanfuehrer - 关于将 std::thread 与变量一起使用,我支持这个答案,但@WilliamClements 也是正确的。大多数 GUI 框架函数并不打算被调用,而是从主应用程序线程调用。也许如果您能更清楚地了解 blocking_lib_func(); 正在做什么,我们可以提供更多帮助。
  • 嗨,blocking_lib_func() 将调用 Qt 主窗口循环并处理信号和槽。这个库是一个与 gui 软件的接口,还有一个应该与这个 blocking_lib_func() 交互的守护进程。当我有一个系统时,我希望主线程启动不同的线程,其中包括只是我系统一部分的 GUI。而不是挂在 GUI 上的主线程 :( 或者是否有一种设计模式可以帮助我解决这个问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
相关资源
最近更新 更多