C++ 如何使用“多线程”;优先权;?

C++ 如何使用“多线程”;优先权;?,c++,c,multithreading,winapi,atl,C++,C,Multithreading,Winapi,Atl,我有多个线程在后台处理多个文件,而程序处于空闲状态。 为了提高磁盘吞吐量,我使用了关键部分来确保没有两个线程同时使用同一个磁盘 (伪)代码如下所示: void RunThread(HANDLE fileHandle) { // Acquire CRITICAL_SECTION for disk CritSecLock diskLock(GetDiskLock(fileHandle)); for (...) { // Do some process

我有多个线程在后台处理多个文件,而程序处于空闲状态。
为了提高磁盘吞吐量,我使用了关键部分来确保没有两个线程同时使用同一个磁盘

(伪)代码如下所示:

void RunThread(HANDLE fileHandle)
{
    // Acquire CRITICAL_SECTION for disk
    CritSecLock diskLock(GetDiskLock(fileHandle));

    for (...)
    {
        // Do some processing on file
    }
}
一旦用户请求处理一个文件,我需要停止所有线程——除了处理请求文件的线程。处理完文件后,我想再次恢复所有线程

考虑到
SuspendThread
是个坏主意,除了处理相关输入的线程外,我如何停止所有线程


我需要什么类型的线程对象/特性——互斥体、信号量、事件或其他?我将如何使用它们?(我希望与Windows XP兼容。)

我建议您以完全不同的方式进行操作。如果您真的希望每个磁盘只有一个线程(我不认为这是一个好主意),那么您应该为每个磁盘创建一个线程,并在将文件排队等待处理时分发文件


为了实现对特定文件的优先级请求,我将在正常处理过程中(当然是在其主队列等待循环中)的几个点上让线程检查“优先级槽”。

我建议您以完全不同的方式进行此操作。如果您真的希望每个磁盘只有一个线程(我不认为这是一个好主意),那么您应该为每个磁盘创建一个线程,并在将文件排队等待处理时分发文件


为了实现对特定文件的优先级请求,我会让一个线程在正常处理过程中的几个点上检查“优先级槽”(当然是在其主队列等待循环中)。

您可以要求线程正常停止。只需检查线程内循环中的一些变量,并根据其值继续或终止工作

关于它的一些想法:

  • 该值的设置和检查应在临界段内进行
  • 因为临界段减慢了线程的速度,所以应该经常进行检查,以便在需要时快速停止线程,很少进行检查,这样线程就不会因为获取和释放临界段而停止。
      您可以要求线程优雅地停止。只需检查线程内循环中的一些变量,并根据其值继续或终止工作

      关于它的一些想法:

      • 该值的设置和检查应在临界段内进行
      • 因为临界段减慢了线程的速度,所以应该经常进行检查,以便在需要时快速停止线程,很少进行检查,这样线程就不会因为获取和释放临界段而停止。
      在每个辅助线程处理一个文件后,检查与该线程关联的条件变量。条件变量可以简单地实现为bool+临界段。或具有联锁交换*功能。老实说,我通常只是在线程之间使用一个不受保护的bool来表示“需要退出”——如果工作线程可能正在睡眠,有时还会使用事件句柄

      为每个线程设置条件变量后,主线程通过WaitForSingleObject等待每个线程退出

      DWORD __stdcall WorkerThread(void* pThreadData)
      {
          ThreadData* pData = (ThreadData*) pTheradData;
      
          while (pData->GetNeedToExit() == false)
          {
              ProcessNextFile();
          }
          return 0;
      }
      
      void StopWokerThread(HANDLE hThread, ThreadData* pData)
      {
         pData->SetNeedToExit = true;
         WaitForSingleObject(hThread);
         CloseHandle(hThread);
      }
      
      struct ThreadData()
      {
          CRITICAL_SECITON _cs;
          ThreadData()
          {
              InitializeCriticalSection(&_cs);
          }
          ~ThreadData()
          {
              DeleteCriticalSection(&_cs);
          }
      
          ThreadData::SetNeedToExit()
          {
              EnterCriticalSection(&_cs);
                _NeedToExit = true;
              LeaveCriticalSeciton(&_cs);
          }
      
          bool ThreadData::GetNeedToExit()
          {
              bool returnvalue;
              EnterCriticalSection(&_cs);
                returnvalue = _NeedToExit = true;
              LeaveCriticalSeciton(&_cs);
              return returnvalue;
          }
      
      };
      

      在每个工作线程处理一个文件后,检查与该线程关联的条件变量。条件变量可以简单地实现为bool+临界段。或具有联锁交换*功能。老实说,我通常只是在线程之间使用一个不受保护的bool来表示“需要退出”——如果工作线程可能正在睡眠,有时还会使用事件句柄

      为每个线程设置条件变量后,主线程通过WaitForSingleObject等待每个线程退出

      DWORD __stdcall WorkerThread(void* pThreadData)
      {
          ThreadData* pData = (ThreadData*) pTheradData;
      
          while (pData->GetNeedToExit() == false)
          {
              ProcessNextFile();
          }
          return 0;
      }
      
      void StopWokerThread(HANDLE hThread, ThreadData* pData)
      {
         pData->SetNeedToExit = true;
         WaitForSingleObject(hThread);
         CloseHandle(hThread);
      }
      
      struct ThreadData()
      {
          CRITICAL_SECITON _cs;
          ThreadData()
          {
              InitializeCriticalSection(&_cs);
          }
          ~ThreadData()
          {
              DeleteCriticalSection(&_cs);
          }
      
          ThreadData::SetNeedToExit()
          {
              EnterCriticalSection(&_cs);
                _NeedToExit = true;
              LeaveCriticalSeciton(&_cs);
          }
      
          bool ThreadData::GetNeedToExit()
          {
              bool returnvalue;
              EnterCriticalSection(&_cs);
                returnvalue = _NeedToExit = true;
              LeaveCriticalSeciton(&_cs);
              return returnvalue;
          }
      
      };
      

      您还可以使用线程池,并通过使用

      通常,池中的线程将休眠,等待I/O完成端口事件/活动。
      当您收到请求时,I/O完成端口将释放线程并开始执行作业。

      您还可以使用线程池并通过使用来调整其工作

      通常,池中的线程将休眠,等待I/O完成端口事件/活动。
      当您有一个请求时,I/O完成端口会释放线程并开始执行一项工作。

      这里的困难并不在于优先级,而是您希望一个线程从它持有的锁中退出,让另一个线程接管它。“优先级”关系到一组可运行线程中的哪一个应该被调度运行——您希望使一个线程不可运行(因为它正在等待另一个线程持有的锁)

      因此,您希望实现(如您所说):

      由于您(明智地)使用了作用域锁,因此我想反转逻辑:

      while (file_is_not_finished) {
          WaitUntilThisThreadCanContinue();
          CritSecLock diskLock(blah);
          process_part_of_the_file();
      }
      ReleasePriority();
      
      ...
      
      void WaitUntilThisThreadCanContinue() {
          MutexLock lock(thread_priority_mutex);
          while (thread_with_priority != NOTHREAD and thread_with_priority != thisthread) {
              condition_variable_wait(thread_priority_condvar);
          }
      }
      
      void GiveAThreadThePriority(threadid) {
          MutexLock lock(thread_priority_mutex);
          thread_with_priority = threadid;
          condition_variable_broadcast(thread_priority_condvar);
      }
      
      void ReleasePriority() {
          MutexLock lock(thread_priority_mutex);
          if (thread_with_priority == thisthread) {
              thread_with_priority = NOTHREAD;
              condition_variable_broadcast(thread_priority_condvar);
          }
      }
      
      了解条件变量——所有最近的操作系统都有条件变量,基本操作都类似。它们也在Boost和C++11中

      如果您无法编写函数
      处理\u文件的\u部分
      ,则无法以这种方式构造它。相反,您需要一个作用域锁,可以释放和恢复disklock。最简单的方法是将其设为互斥体,然后可以使用相同的互斥体等待condvar。您仍然可以使用mutex/condvar对和具有优先级的
      thread\u
      对象,方式大致相同

      您可以根据系统对优先级更改的响应程度来选择“部分文件”的大小。如果你需要它的响应速度非常快,那么这个方案就不起作用了——这是一种合作的多任务处理

      我对这个答案并不完全满意,如果有很多其他线程已经在同一个磁盘锁上等待,那么具有优先级的线程可能会很长时间处于饥饿状态。为了避免这种情况,我会多加考虑。可能不应该有