zoukankan      html  css  js  c++  java
  • <转>多线程中的lua同步问题

    转自 http://www.cnblogs.com/ghost240/p/3526185.html

    最近写paintsnow::start时出现了一个非常麻烦的BUG,程序的Release版本大约每运行十几次就会有一次启动时崩溃(Debug版本还没崩溃过),崩溃点也不固定。经过简单分析之后,确定是线程同步的问题。于是便修改了线程通信的代码,并使用pthread_mutex_lock/unlock来防止冲突。重新编译后,崩溃频率有所减少。但是每运行约四十次,还是免不了崩溃一次,而且冷启动时崩溃概率更大。

    在VC中的Release版本中设置Generate Debug Info后,重复多次运行程序,好不容易得到了几次崩溃记录。综合这几次的崩溃点,可以发现崩溃基本都发生在重分配内存(operator new())时,而且调用堆栈中还显示调用过程中有luaVM的参与。经过多日跟踪,终于发现问题所在,特作记录。

    首先简单说一下paintsnow的组织结构。paintsnow::start主要是由两个线程并行执行的,其中一个负责构架、绘图、消息处理等,由底层核心paintsnow.lib提供,另一个执行lua脚本,由luaVM和一些Paintsnow API构成。由于两个线程有时候需要调用另一个线程所提供的功能,因此可能会出现两个线程冲突的问题。之前的代码仅仅是对脚本线程call核心线程时做过调用转接和加锁处理,但是实际上有时核心线程也会call脚本(通常出现在各种回调函数中)。

    网上的资料说解决多线程调用同一个luaVM的有效方案是使用lua_newthread来创建一个脚本线程单元,然后用新创建的单元作为lua_State来call。这一招在通常情况下是非常管用的,因为它成功避免了lua栈上的冲突。painsnow以前的方案就是这样写的。可是问题就出在lua本身为了兼容标准,并不包含线程同步的处理函数,所谓的newthread只是逻辑上的thread而非操作系统概念的thread,因此这样调用luaVM依然存在着重入的风险,特别是在内存重分配时会产生意思不到的错误。

    当然,对于lua这种设计得非常优雅的库,自然对多线程有过考虑。通过lua的源码可以看出,lua在每一个不可重入的函数中都用lua_lock创建了一个锁以保证同步。默认情况下,由于同步锁并不包含在标准库中,所以lua_lock实际只是一个空宏:(llmits.h中有定义)

    #define lua_lock(L) ((void)0)

    如果想要添加多线程支持,需要重写它和lua_unlock两个宏。这不是难事,以添加pthread提供锁功能为例:

    在lstate.h中,对GlobalState结构新加一个成员:

    pthread_mutex_t lock;

    然后在lua_newstate中添加初始化代码:

    pthread_mutex_init(&g->lock, NULL);

    接着重定义lock/unlock宏(写在原定义前面即可):

    #define lua_lock(L) pthread_mutex_lock(&(G(L)->lock));

    #define lua_unlock(L) pthread_mutex_unlock(&(G(L)->lock));

    最后在close_state函数的末尾添加两行:


    static void close_state (lua_State *L) {
      global_State *g = G(L);
      luaF_close(L, L->stack);  /* close all upvalues for this thread */
      luaC_freeallobjects(L);  /* collect all objects */
      luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
      luaZ_freebuffer(L, &g->buff);
      freestack(L);
      lua_assert(gettotalbytes(g) == sizeof(LG));
     pthread_mutex_unlock(&g->lock);
     pthread_mutex_destroy(&g->lock);

      (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);  /* free main block */
    }

    vc++ lua线程同步代源码修改 见 http://www.cnblogs.com/zhangdongsheng/p/3679024.html

  • 相关阅读:
    VuGen错误处理函数
    LR的日志
    创建性能测试脚本时如何选择HTML模式和URL模式
    Java变量
    查找&排序
    selenium执行JS
    Python中 is 和 == 的区别
    Python中 and or的计算规则
    selenium使用location定位元素坐标偏差
    错误:Could not find an available JavaScript runtime
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/3667796.html
Copyright © 2011-2022 走看看