【问题标题】:how do i lock access to a bool with a mutex?如何使用互斥锁锁定对布尔的访问?
【发布时间】:2018-06-06 13:40:44
【问题描述】:

已解决!:我在新线程中复制 Map 的实例,但不使用引用。

我正在学习如何使用多线程。对于这个我正在编写一个小游戏,我希望游戏在主线程中运行,并且关卡的下一个块应在另一个线程中加载。为此,我在向量周围设置了一个互斥锁,以告诉加载线程接下来要加载什么。在这个互斥体中,我还有一个布尔值来告诉线程何时终止。

在 Map::Map() 中初始化线程

pending_orders_mutex = SDL_CreateMutex();
can_process_order = SDL_CreateCond();
chunk_loader_thread = SDL_CreateThread(Map::chunk_loader,"chunk_loader_thread",(void*)this);

加载线程

int Map::chunk_loader(void * data)
{
    Map map = *(Map*)data;
    bool kill_this_thread = false;

    Chunk_Order actual_order;
    actual_order.load_graphics = false;
    actual_order.x = 0;
    actual_order.y = 0;



    while (!kill_this_thread)
    {
        SDL_LockMutex(map.pending_orders_mutex);            // lock mutex
        printf("3-kill_chunk_loader_thread: %d\n", map.kill_chunk_loader_thread);
        kill_this_thread = map.kill_chunk_loader_thread;
        printf("4-kill_chunk_loader_thread: %d\n", map.kill_chunk_loader_thread);
        if (!kill_this_thread)
        {
            if (map.pending_orders.size())
            {
                actual_order = map.pending_orders.back();
                map.pending_orders.pop_back();
                printf("in thread processing order\n");
            }
            else
            {
                printf("in thread waiting for order\n");
                SDL_CondWait(map.can_process_order, map.pending_orders_mutex);
            }
        }
        SDL_UnlockMutex(map.pending_orders_mutex);          // unlock mutex

        //load actual order
    }
    printf("thread got killed\n");
    return 0;
}

杀死线程(主线程)

SDL_LockMutex(pending_orders_mutex);            // lock mutex
  printf("setting kill command\n");
  printf("1-kill_chunk_loader_thread: %d\n", kill_chunk_loader_thread);
kill_chunk_loader_thread = true;                // send kill command
  printf("2-kill_chunk_loader_thread: %d\n", kill_chunk_loader_thread);
SDL_CondSignal(can_process_order);              // signal that order was pushed
SDL_UnlockMutex(pending_orders_mutex);          // unlock mutex

SDL_WaitThread(chunk_loader_thread, NULL);

控制台输出

3-kill_chunk_loader_thread: 0
4-kill_chunk_loader_thread: 0
in thread waiting for order
setting kill command
1-kill_chunk_loader_thread: 0
2-kill_chunk_loader_thread: 1
3-kill_chunk_loader_thread: 0
4-kill_chunk_loader_thread: 0
in thread waiting for order

为什么主线程不改变加载线程中的“kill_chunk_loader_thread”布尔值?

【问题讨论】:

  • 您对互斥锁的工作原理有深入的了解吗?您不会通过锁定变量来保护访问,而是通过互斥来保护并发线程访问:每当访问变量时,请确保线程首先为其获取特定的锁定。
  • 在您学习多线程时支持使用互斥锁。不是每个人都这样做 --- 看着自己
  • 你什么时候将map.kill_chunk_loader_thread分配给0或1?我会在上面设置断点并检查是否按预期设置
  • 阅读一些POSIX thread tutorial。考虑使用std::atomic_bool 及其load & store
  • 扩展 Josh Detwiler 所说的内容,如果您想保护一个变量或相关变量的 ,您需要确保在您的在互斥锁未锁定时使用变量的代码。此外,您需要确保它始终是 same 互斥体。 (锁定错误的互斥锁是一个常见的菜鸟错误。)

标签: c++ multithreading sdl-2


【解决方案1】:

首先,你应该尝试在问题中上传一个最小的完整程序。

它看起来像你设置kill_chunk_loader_thread = true

但你没有设置map.kill_chunk_loader_thread = true

map 声明部分从您的问题中消失,但我猜您没有使用对局部或全局变量的引用,或者您只是执行结构复制,因此当您更改一个结构时另一个不会完全受到影响。

编辑:

Map map = *(Map*)data; 复制 map 结构(我猜是默认的复制构造函数)所以从现在开始,如果源映射更改副本不会。

您应该继续使用指针,如下所示:Map* pMap = (Map*)data; 并像这样检查指针:kill_this_thread = pMap->kill_chunk_loader_thread; 所以你从源映射中读取。

【讨论】:

  • 稍微扩展了源代码。我将指向 Map 类实例的指针指向线程。它是此类的唯一实例。
猜你喜欢
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 2013-12-10
  • 2018-05-23
  • 1970-01-01
相关资源
最近更新 更多