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兼容。)我建议您以完全不同的方式进行操作。如果您真的希望每个磁盘只有一个线程(我不认为这是一个好主意),那么您应该为每个磁盘创建一个线程,并在将文件排队等待处理时分发文件
为了实现对特定文件的优先级请求,我将在正常处理过程中(当然是在其主队列等待循环中)的几个点上让线程检查“优先级槽”。我建议您以完全不同的方式进行此操作。如果您真的希望每个磁盘只有一个线程(我不认为这是一个好主意),那么您应该为每个磁盘创建一个线程,并在将文件排队等待处理时分发文件
为了实现对特定文件的优先级请求,我会让一个线程在正常处理过程中的几个点上检查“优先级槽”(当然是在其主队列等待循环中)。您可以要求线程正常停止。只需检查线程内循环中的一些变量,并根据其值继续或终止工作 关于它的一些想法:
- 该值的设置和检查应在临界段内进行
- 因为临界段减慢了线程的速度,所以应该经常进行检查,以便在需要时快速停止线程,很少进行检查,这样线程就不会因为获取和释放临界段而停止。
- 您可以要求线程优雅地停止。只需检查线程内循环中的一些变量,并根据其值继续或终止工作
关于它的一些想法:
- 该值的设置和检查应在临界段内进行
- 因为临界段减慢了线程的速度,所以应该经常进行检查,以便在需要时快速停止线程,很少进行检查,这样线程就不会因为获取和释放临界段而停止。
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完成端口会释放线程并开始执行一项工作。这里的困难并不在于优先级,而是您希望一个线程从它持有的锁中退出,让另一个线程接管它。“优先级”关系到一组可运行线程中的哪一个应该被调度运行——您希望使一个线程不可运行(因为它正在等待另一个线程持有的锁) 因此,您希望实现(如您所说): 由于您(明智地)使用了作用域锁,因此我想反转逻辑:
了解条件变量——所有最近的操作系统都有条件变量,基本操作都类似。它们也在Boost和C++11中 如果您无法编写函数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); } }
,则无法以这种方式构造它。相反,您需要一个作用域锁,可以释放和恢复disklock。最简单的方法是将其设为互斥体,然后可以使用相同的互斥体等待condvar。您仍然可以使用mutex/condvar对和具有优先级的处理\u文件的\u部分
对象,方式大致相同 您可以根据系统对优先级更改的响应程度来选择“部分文件”的大小。如果你需要它的响应速度非常快,那么这个方案就不起作用了——这是一种合作的多任务处理 我对这个答案并不完全满意,如果有很多其他线程已经在同一个磁盘锁上等待,那么具有优先级的线程可能会很长时间处于饥饿状态。为了避免这种情况,我会多加考虑。可能不应该有thread\u