从 cpp 中的父线程暂停和恢复线程

Posted

技术标签:

【中文标题】从 cpp 中的父线程暂停和恢复线程【英文标题】:Pause and resume thread from parent thread in cpp 【发布时间】:2016-09-22 06:10:36 【问题描述】:

我正在使用 cpp 线程库。我有一个父线程 T1,它有一个子线程 T2。 T2 只会遍历一些项目并进行一些处理。我需要使用来自 T1 的函数调用从 T1 暂停和恢复 T2。 T1 和 T2 属于同一类。当特定事件到达 T1 时,我需要它来停止处理数据;请不要推荐任何其他线程实现库。

    C::t2_func
      for(int i=0;i<data.size();i++)
        process_data(data[i]);
    
    C::spawn()
       t2 = std::make_unique<std::thread>(std::bind(&C::t2_func, this));
    
    C::pause()
         //pause t2
    
    C::resume()
         //resume t2
    

【问题讨论】:

【参考方案1】:

虽然不可能完全在线程外部暂停 STL 线程(一些具有更广泛线程管理功能的特定平台线程可能支持它),但可以在以下人员的配合下暂停线程线程。请注意,这意味着暂停不会在线程执行期间的任意点发生,而只会在线程函数支持暂停的特定点发生。

暂停线程的核心非常简单:一个指示是运行还是暂停的标志。访问共享线程数据,例如标志,必须同步;这是一个次要的方面,必然使实现更加复杂,尽管不是特别复杂。

通过mutex上的锁(如lock_guardunique_lock)实现同步;互斥锁确保了代码的关键部分是互斥的(即不会被另一个打断),而锁负责管理互斥锁的锁定和解锁。

此外,condition variable 用于表示线程应该运行:暂停线程waits 直到标志表示“运行”,恢复函数notifies 表示标志为“运行”。由于条件变量访问共享数据,它还使用互斥锁上的锁。 std::condition_variable 支持两种等待方式:一种只是等待通知但可能会受到虚假唤醒的影响,另一种采用可调用谓词并等待通知和谓词返回 true(允许虚假唤醒)唤醒被忽略)。一般来说,后者是你想要的。

假设线程函数具有 void 返回值,示例实现可能是:

// shared data, threading primitives
bool pause = false;
std::condition_variable cv;
std::mutex m;

// T2's main thread function
void C::t2_func() 
  for(int i = 0; i < data.size(); i++)
    // wait until unpause is signaled
    nap();
    
    // do some work
    process_data(data[i]);
  


void C::spawn() 
   t2 = std::make_unique<std::thread>(std::bind(&C::t2_func, this));


// thread management
void C::nap() 
    // must use a `unique_lock` with a `condition_variable`, not a `lock_guard`
    std::unique_lock<decltype(m)> lk(m);
    cv.wait(lk, [] return ! pause; );


void C::pause() 
     //pause
     std::lock_guard<decltype(m)> lk(m);
     pause = true;


void C::resume() 
     std::lock_guard<decltype(m)> lk(m);
     pause = false;
     cv.notify_one();
     //resume t2

【讨论】:

【参考方案2】:

您不能在外部暂停线程。但是线程可以自行暂停。考虑使用std::condition_variable 和布尔标志is_paused。然后在每次迭代的工作线程中锁定一个互斥锁,检查线程是否应该暂停,如果应该暂停,请等待条件变量,直到 is_paused 重置为 false。然后在你的主线程中锁定互斥锁,更改is_paused 并通知条件变量。

【讨论】:

【参考方案3】:

许多人在论坛上询问是否可以暂停、恢复或取消一个主题,遗憾的是目前我们不能。但是如果有迫切的需要,我有时会这样实现。使您的函数增量(细粒度),以便它可以在循环中连续执行,您可以在其中进行操作,如下面的简单示例所示:

void main()

enum tribool  False,True,Undetermine;

bool running = true;
bool pause = false;

std::function<tribool(int)> func = [=](long n)
  
    long i;

    if (n < 2) return False;
    else
    if (n == 2) return True;

    for (i = 2; i < n; i++)
    
        while (pause)
        
            if (!pause) break;
            if (!running) return Undetermine;
        
        if (n%i == 0) return False;
    
    return True;
   ;

    std::future<tribool> fu = std::async(func,11);

    pause = true; //testing pause
    pause = false;

   auto result = fu.get();
   if (result == True) std::cout << " Prime";
   else
   if (result == False) std::cout << " Not Prime";
   else
    std::cout << " Interrupted by user";

   return ;
 

【讨论】:

以上是关于从 cpp 中的父线程暂停和恢复线程的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 threading 模块暂停和恢复线程?

利用ManualResetEvent来来控制异步调用的打印的线程的暂停和恢复(转)

暂停和恢复 Grand Central Dispatch 线程

在 C# 中暂停/恢复线程

如何在 C++ 中暂停和恢复 POSIX 线程?

Java ExecutorService 暂停/恢复特定线程