Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 保持线程长时间锁定_C++_Multithreading - Fatal编程技术网

C++ 保持线程长时间锁定

C++ 保持线程长时间锁定,c++,multithreading,C++,Multithreading,编辑2:为了澄清我的问题,我正在努力编写代码来阻止和恢复一个线程来做一些工作(在本例中,读取一些文件) 编辑3:添加了void Loader::RequestToLoadRegion(Region&Region)的函数定义 我想在我的游戏中创建一个基本的流媒体系统。我需要一个线程来读取游戏文件,这些文件将被封锁的大部分时间,并不时醒来。以下是我目前的设计工作原理 每当玩家接近世界上没有RAM加载的区域时, 游戏向(唯一)加载程序对象发送一个请求,以加载该区域(加载程序类表示流媒体系统)。 每个区

编辑2:为了澄清我的问题,我正在努力编写代码来阻止和恢复一个线程来做一些工作(在本例中,读取一些文件)

编辑3:添加了void Loader::RequestToLoadRegion(Region&Region)的函数定义

我想在我的游戏中创建一个基本的流媒体系统。我需要一个线程来读取游戏文件,这些文件将被封锁的大部分时间,并不时醒来。以下是我目前的设计工作原理

每当玩家接近世界上没有RAM加载的区域时, 游戏向(唯一)加载程序对象发送一个请求,以加载该区域(加载程序类表示流媒体系统)。 每个区域都有一个与之关联的文件列表,这些文件将被读取以创建游戏数据并加载到RAM中

装载分两步完成:

  • 步骤1:读取所有文件并将其内容推送到队列中
  • 步骤2:处理存储在此队列中的原始文件数据
Loader对象使用Reader对象读取所有文件,并将其内容推送到前面提到的队列中。在加载器的构造函数中,将构造Reader对象,该对象将启动一个用于读取文件的线程。但是,该读取线程在大多数情况下都会被阻塞,并且只有当加载程序接收到加载新区域的请求时才会被加载程序唤醒

在每帧开始时,加载程序将获得控制,并检查其当前状态,无论是否加载。如果它处于加载状态,那么它将尝试访问受互斥锁保护的队列。如果它从队列中获得一个项目,它将处理它并将控制权交还给游戏。队列中的下一个项目将在下一帧处理,依此类推,直到区域加载完成

我知道如何使用互斥来实现这一部分。然而,我有一些麻烦来保持阅读线程阻塞,并在加载请求到达时唤醒它。我已经学会了如何在基本程序中使用std::condition_变量,目前的解决方案如下:

  • 在创建加载程序时,它会锁定互斥锁,以便读取线程保持阻塞状态
  • 当游戏向加载程序发送请求时,后者将读取器的标志(m_canRead)设置为true,并使用条件变量调用notify_one(),以唤醒读取线程
  • 当读取线程即将读取文件时,它调用m_loader.OnStartReading(),以便加载程序锁定m_canReadMutex互斥体。然后控制返回到读取文件的读取器

    这个设计中我遇到的最大问题是,我了解到您通常会在短时间内锁定互斥体,并且您通常会将其与std::lock_guard一起使用,这样,如果出现异常,互斥体将被解锁

//这是读取线程运行的函数
//m_readingThread=std::thread(&Reader::Run,this);
void Reader::Run(){
while(true){
{
std::unique_lock ul(m_canReadMutex);
m|u canReadCondVar.wait(ul,[this](){返回m|u quit | m|u canRead;});
//确定唤醒的原因
如果(m_quit){//游戏想退出吗?我们打破了游戏
break;//到达Run()函数末尾的循环
}//这样我们就可以加入()读取线程。
//如果控件到达这一行,则表示线程被
//加载请求,可以读取。结束括号“将运行析构函数”
//用于解锁互斥锁的std::unique_锁。
}
{//当控件到达此范围时,表示m_canRead为true。
m_loader.OnStartReading();//将锁定互斥锁m_canReadMutex
ReadFiles();
}
}//结束时(true)
}//结束函数void Run()
void Reader::ReadFiles(){
/*读取所有文件并将数据推入队列*/
}
void加载程序::OnStartReading(){
m_canReadMutex.lock();
}
//此函数用于解锁互斥锁并唤醒读取线程。
无效加载程序::RequestToLoadRegion(区域和区域){
/*获取与区域关联的文件列表*/
m_canReadMutex.unlock();
m_reader.m_canRead=true;//设置标志,使读取器wait()中的谓词计算为true
m_canReadCondVar.notify_one();//唤醒读取器线程
}

您的代码很好。这是我等待值的标准代码:

void
WaitCondition::wait() {
    unique_lock<std::mutex> lock(myMutex);
    while (!value) {
        condVar.wait(lock);
    }
}
void
WaitCondition::wait(){
唯一锁(myMutex);
而(!值){
等待(锁);
}
}
等待condVar实际上会释放锁,直到等待完成。所以你很好


(根据雷蒙德的建议编辑。)

您的代码很好。这是我等待值的标准代码:

void
WaitCondition::wait() {
    unique_lock<std::mutex> lock(myMutex);
    while (!value) {
        condVar.wait(lock);
    }
}
void
WaitCondition::wait(){
唯一锁(myMutex);
而(!值){
等待(锁);
}
}
等待condVar实际上会释放锁,直到等待完成。所以你很好


(根据Raymond的建议编辑)

std::unique_lock
std::lock_guard
非常相似:它在构造函数中获取锁,并在析构函数中释放锁。不同之处在于,它还提供了额外的功能,其中之一是您可以将它与
std::condition\u variable::wait
一起使用

调用
wait
时,库会将线程标记为waiting,然后解锁互斥锁和块。当条件变量解除阻塞时(由于调用
notify\u one
notify\u all
或错误),它会在调用
wait
返回之前重新锁定互斥锁。因此,互斥锁在
wait
调用前后都会被锁定,但在
wait
调用期间不会被锁定

更新:

OnStartReading
直接锁定互斥锁,并且没有相应的解锁。这真的很不寻常:这意味着互斥锁将永远被锁定,从现在开始

我会的