我正在进行广泛使用多线程的模拟。问题是,到目前为止,我从未使用过任何互斥对象来保护我的数据。结果是,我得到了大量的分段错误。
我正在尝试使用互斥锁进行锁定/解锁:读/写但这会导致我的另一个段错误:
#0 77D27DD2 ntdll!RtlEnumerateGenericTableLikeADirectory() (C:\Windows\system32\ntdll.dll:??)
#1 00000000 ??() (??:??)
当然,我创建了一个测试项目,在这个项目中我为基本情况应用了锁定/解锁的东西并且它工作正常,这是一个基本的例子,它展示了如何使用GLFW处理Mutex对象:
#include <GL/glfw.h>
#include <iostream>
#include <vector>
using namespace std;
vector<int> table;
GLFWmutex th_mutex;
void GLFWCALL Thread_1(void* arg) {
glfwLockMutex(th_mutex);
table.pop_back();
glfwUnlockMutex(th_mutex);
}
void GLFWCALL Thread_2(void* arg) {
glfwLockMutex(th_mutex);
table.erase(table.begin());
glfwUnlockMutex(th_mutex);
}
int main()
{
bool running = true;
GLFWthread th_1, th_2;
glfwInit();
if( !glfwOpenWindow( 512, 512, 0, 0, 0, 0, 0, 0, GLFW_WINDOW ) )
{
glfwTerminate();
return 0;
}
glfwSetWindowTitle("GLFW Application");
for(int i = 0;i < 10; i++) {
table.push_back(i);
}
th_mutex = glfwCreateMutex();
th_1 = glfwCreateThread(Thread_1, NULL);
th_2 = glfwCreateThread(Thread_2, NULL);
while(running)
{
// exit if ESC was pressed or window was closed
running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam( GLFW_OPENED);
}
glfwTerminate();
return 0;
}
项目,我工作的更大,我有5个线程在运行,并且同时访问了很多矢量,地图,队列。在代码的某处,我尝试做类似的事情:
void GLFWCALL CreateVehicleThread(void* arg) {
int index = (*static_cast<PulseStateByEntrance*>(arg)).index;
double t_initial = (*static_cast<PulseStateByEntrance*>(arg)).initial_time;
double t_final = (*static_cast<PulseStateByEntrance*>(arg)).final_time;
int pulse = (*static_cast<PulseStateByEntrance*>(arg)).pulse;
int nb_entrance = (*static_cast<PulseStateByEntrance*>(arg)).nb_entrance;
int min_time_creation = static_cast<int>(ceil(3600 / pulse));
while((glfwGetTime() - (*static_cast<PulseStateByEntrance*>(arg)).initial_time)
< ((*static_cast<PulseStateByEntrance*>(arg)).final_time - (*static_cast<PulseStateByEntrance*>(arg)).initial_time)) {
double t_elapsed = glfwGetTime() - t_initial;
if(t_elapsed > min_time_creation) {
**int nb_vehicle_per_cycle = static_cast<int>((t_elapsed * pulse)/3600);
glfwLockMutex(th_mutex);
VehicleManager::CreateVehicles(nb_vehicle_per_cycle, nb_entrance);
glfwUnlockMutex(th_mutex);**
t_initial = glfwGetTime();
}
}
}
之所以,我将我的VehicleManager:CreateVehicles()方法置于锁定/解锁之间是因为在这种方法中有这一行:
VehicleManager::vehicles_.push_back(vehicle);
所以我想保护矢量:vehicles_。但是,结果我得到了上面的段错误。即便如此:
glfwLockMutex(th_mutex);
VehicleManager::vechicles_.push_back(vehicle);
glfwUnlockMutex(th_mutex);
我得到了同样的段错误。
我希望,我已经让自己清楚了解你的问题的本质。我想,并非所有人都使用GLFW这就是为什么我给你第一个基本的例子,这样你才能理解互斥体如何与这个库一起工作。
谢谢!
答案 0 :(得分:1)
没有足够的信息。但是作为猜测,看起来mutex没有正确创建(看起来像一个NULL引用)。找到你调用glfwCreateMutex()的位置,并确保返回一个有效值。
与您的问题无关,请注意:
不要这样做:
glfwLockMutex(th_mutex);
<ACTION>
glfwUnlockMutex(th_mutex);
这是C风格,因此不是例外安全 您应该设置一个类,以便在构造函数中调用锁,并在析构函数中调用unlock。然后有一个这个类的锁对象。因此,锁定和解锁通常作为对象创建解除的一部分发生,因此在存在异常时锁将被正确释放。
princeiple是RAII,他们在这里有很多文章。
示例:
class MutexLocker
{
public:
MutexLocker(GLFWmutex& mutex)
:m_mutex(mutex)
{
glfwLockMutex(m_mutex);
}
~MutexLocker()
{
glfwUnlockMutex(m_mutex);
}
private:
GLFWmutex& m_mutex;
};
void myAction()
{
MutexLocker lock(th_mutex);
// Do stuff here:
}
答案 1 :(得分:1)
您可以包装容器,这将使您的代码更容易理解:
template<typename T>
class MultithreadedVector
{
public:
void pushback( T data )
{
glfwLockMutex(m_mutex);
m_container.push_back( data );
glfwUnlockMutex(m_mutex);
}
//then similar for erase etc
private:
std::vector<T> m_container;
GLFWmutex m_mutex;
};