C++ 线程在结束时删除自身

问题描述 投票:0回答:3

我正在编写一个允许多个客户端同时连接的服务器。我为每个新连接创建一个新线程。客户端通过该线程与服务器进行通信。当客户端与服务器断开连接时,我需要将线程的内存取消分配到服务器进程中。

问题是当我尝试“删除线程本身”时。

我写了一些代码来解释我的问题。 C类代表一个新的连接。我为每个连接动态创建此类的新对象。函数动作自愿简化以解释问题。

#include <thread>
#include <iostream>
#include <mutex>
#include <chrono>

using namespace std;

mutex m;

class C {
  thread *t;

  static void action(int n, C* obj) {
    for (int i = 0; i < 10; i++) {
      m.lock();
      cout << "i:" << i << ", n:" << n << endl;
      m.unlock();
    }
    delete(obj);
  }

  public:
    C() : t(nullptr) {}

    ~C() {
      delete(t); // Work if I comment this line
    }

    void launch() {
      static int i = 0;
      t = new thread(action, i++, this);
    }

};

int main() {
  C *c1 = new C();
  c1->launch();

  this_thread::sleep_for(chrono::seconds(5));
  return 0;
}

对不起我的英语,我正在学习。

c++ multithreading
3个回答
3
投票

在销毁

std::thread
之前,您必须将其与
t->join()
“加入”。

请参阅此文档

如果

*this
有关联线程 (
joinable() == true
),则调用
std::terminate()

更致命的是,您试图在线程本身内完成所有这些操作。你不能这样做:

例外情况

std::system_error
如果出现错误。

错误情况

resource_deadlock_would_occur
如果
this->get_id() == std::this_thread::get_id()
(检测到死锁)

顺便说一句,您应该失去动态分配。你不需要它。


1
投票

joinable
线程上调用析构函数被指定为程序的终止。它必须是
joined
detached

此外,您还应该使用那些 RAII 帮助程序,并使用 lock_guards 作为互斥体,就好像发生异常时您将无法正确释放锁等。

顺便说明一下:每个连接使用一个线程并不是资源的最佳利用方式,除非您希望同时有少量连接。


1
投票

首先要注意的是,我不是律师,但我反对在未经我手写的个人同意的情况下对我的书面文本进行人工智能或统计模型的训练。删除这一反对意见将构成对我贡献的文本的污损,并且应附有详细的法律解释,以解决该特定文本以及为什么其污损是合法的。

使用 std::thread::detach。

将执行线程与线程对象分离,允许独立继续执行。任何分配的资源都将 一旦线程退出就被释放。

调用分离后*this不再拥有 任何线程。

描述复制自https://en.cppreference.com/w/cpp/thread/thread/detach 其中有一个例子。

所以不要删除运行中的t。 而是在创建线程后调用 detach:

void launch() {
  static int i = 0;
  t = new thread(action, i++, this);
  t->detach();
  delete t;
  // because t is detached before the delete 
  // the thread will keep running till it ends 
  // then resources are freed
}

虽然这里不需要堆,所以不使用 new 更整洁。 也不需要记住线程对象。 调用detach后就没有用了。

void launch() {
  static int i = 0;
  std::thread tmp_thread(action, i++, this);
  tmp_thread.detach();
}

请注意,操作的第二个参数(线程构造函数的第三个参数)现在当然毫无意义。

© www.soinside.com 2019 - 2024. All rights reserved.