互斥体使用不正确?延续过去的问题 [英] Mutex not correctly used? Continuation of past questions

查看:89
本文介绍了互斥体使用不正确?延续过去的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第二个问题是该线程的延续:如何执行Windows选择线程的内存?

I have a second question that is a continuation of this thread : How Does Windows Pick memory for threads?

void ThreadTest(LPTSTR* Pointer, mutex* MutexPtr)
{
    MutexPtr->lock();   
    wcout << *Pointer << endl;
    MutexPtr->unlock();
    return;
}
void FakeMain()
{
    mutex Mut;
    mutex* MutPtr = &Mut;
    LPTSTR Image = L"First String";
    LPTSTR* StrPointer = &Image;
    thread Test(ThreadTest, StrPointer, MutPtr);
    MutPtr->lock();
    if (true)
    {

        NewStringFunction(Image);
        MutPtr-unlock() // Added with the comment of Mike
        Test.join();        
        LPTSTR* StrPointer = &Image;        
        thread Test(ThreadTest, StrPointer, MutPtr);                
    }

    MutPtr->lock();
    Test.join();
    MutPtr->unlock();
    return;
};
void NewStringFunction(LPTSTR& Image)
{
    LPTSTR TempString = L"New String for new Thread";
    Image = TempString;
    return;
};

上面的代码是模拟我遇到问题的代码. 流程应如下:

The Code above is emulates my code I am having issues with. The flow should be as follows:

  • FakeMain()初始化变量并设置一个字符串;
  • FakeMain然后为要打印的字符串创建一个线程.
  • 新线程将打印字符串.
  • 打印线程被破坏,并且一个单独的外部函数创建了一个新字符串.
  • 创建了一个新线程来打印此新消息

我有一个"if"语句,因为实际的代码在if语句中有一个线程,我想确保内存分配代表了这一点. 在单独的函数中更改字符串,因为这是实际代码执行此操作的方式. 我销毁了第一个线程,因为在实际代码中,该线程正在显示一个窗口,该窗口会改变大小,因此需要一个新线程.

I have an "if" statement because the real code has a thread being made inside an if statement, i wanted to make sure the memory allocation represented this. The string is changed in a separate function because this is how the real code does this. I destroy the first thread because in the real code, the thread is displaying a window, which changes size, thus needs a new thread.

通过编写此代码,我感到我的互斥体未正确实现.这段代码没有给出字符串错误,但我认为互斥体正在被线程覆盖(我认为).我不确定在程序运行时观察内存,第一个线程实例可能会覆盖互斥量.主线程中的最后一个Mutex.lock()引发错误.我是否正确使用互斥锁?有没有一种更清洁的方法来锁定/停止线程?

From writing this code I feel my mutexs are not implemented correctly. This code is not giving string errors but I think the mutex is being over written by the thread (i think). Watching the memory as the program runs, the first thread instance may over write the mutex, I am not sure. The last mutex.lock() in the main thread is throwing an error. Am I using mutexes correctly? Is there a cleaner way I should be locking/stopping threads?

推荐答案

不要使用互斥锁,也不要共享内存.

Don't use a mutex and don't share the memory.

暴力法:

发件人所需要做的就是

Message msg = new Message(<important information>);
// send msg

在接收代码中,

// use msg  
delete msg;

非常容易编写和使用,但是会发生内存泄漏:如果永远不会处理一条消息,则它永远不会退还RAM.

Very simple to write and use, but has a memory leak: if a message never gets serviced, it never gives back the RAM.

更好的版本可能会变得非常复杂.这是一个简单的概述:

Better versions can get very complicated. Here is an outline for a simple one:

Create a pool of Messages
Assign all messages to a FreeList
Create a mutex to protect FreeList

FreeList是当前未使用的消息列表.当需要发送消息时,第一条消息将从FreeList中删除,并传递给调用者.呼叫者使用要发送的信息填写Message,然后发送Message.

FreeList is a list of messages that are not currently being used. When a Message needs to be sent, the first Message is removed from FreeList and handed to the caller. The caller fills out Message with the information to be sent and then sends the Message.

接收者负责将消息返回到FreeList.

The receiver is responsible for returning the Message to FreeList .

添加一些功能来管理FreeList

Add a few functions to manage FreeList

GetMsg <changed to prevent collision with Windows GetMessage function>
    Message = NULL
    acquire mutex
    if FreeList not empty
        remove Message from FreeList
    release mutex
    return message            

ReturnMsg
    acquire mutex
    Add Message to FreeList
    release mutex

发件人有点复杂

Message msg = GetMessage()
If msg not NULL
    msg.set(<important information>);
    std::thread temp(ThreadTest, msg);
    temp.detatch
else
    // log and handle <- can be simple like abort or complicated like recover lost Messages

接收器仍然非常简单

// use msg  
ReturnMessage(msg);

这可以限制内存泄漏,并且可以轻松地跟踪哪些消息从未返回(在池中,但不在FreeList中),因此您可以尝试跟踪哪些作业被阻塞或炸毁.修复锁定或爆炸是另一个问题.

This has a cap on the memory leak and can make it easy to track which Messages never got returned (in pool, but not in FreeList) so you can attempt to track down which jobs got blocked or blown up. Fixing the lock or blow-up is another problem.

OP我认为我有正确的主意.这是基本线程功能的胆量.它在后台运行时一直挂出,直到发送终止消息为止.它阻止等待消息,使用消息,然后将其放回FreeList中,并阻塞直到另一条消息到达为止.

OP had a good idea that I think I have about right. Here are the guts of a basic thread function. It hangs out in the background running until sent a terminate message. It blocks waiting for a message, consumes the message, and then puts it back in FreeList and blocks until another message arrives.

void threadfunc()
{
    MSG winmsg;
    BOOL rval;

    while (GetMessage(&winmsg, (HWND__ *) -1, 0, 0) != -1)
    {
        Message * msg = (Message *)winmsg.wParam;
        // do stuff with msg
        ReturnMsg(msg);
    }
    // GetMessage failed. Find out why and try to recover or die gracefully
}

它需要得到类似

bool PostMsg(<Important Information>,
             DWORD & BackgroundThreadId)
{
    Message * msg = GetMsg();
    if (msg != NULL)
    {
         msg.set(<Important Information>)
        if (PostThreadMessage(BackgroundThreadId,
                              WM_USER,
                              (WPARAM) msg,
                              0); != 0)
        {
            return true;
        }
        else
        {
            // failed. Find out why and try to recover or die gracefully
            ReturnMsg(msg);
            return false;
        }
    }
    else
    {
        // out of free messages. Try to find out why
    }
}

PostMsg将消息送入后台线程的消息队列.消息来自FreeList,只有FreeList需要互斥保护.可以使用多个线程. 我不认为可以使用std :: thread来完成此操作,因为std :: thread不能访问底层线程句柄(只需检查即可完成)或线程的消息队列.一切都是基于Windows调用的,所以请不要考虑可移植性.

PostMsg feeds Messages into the background thread's message queue. Messages come from the FreeList and only the FreeList needs mutex protection. More than one thread can be in use. I don't think this can be done with std::thread since std::thread doesn't give access to the underlying thread handle (Just checked, it can be done) or the thread's message queue. It'as all based on Windows calls anyway, so forget about portability.

这篇关于互斥体使用不正确?延续过去的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆