今天在改一个程序,改成部分逻辑用lua写,这个程序是多线程的。将程序中部分逻辑改成lua之后,各种非法访问内存错误,各种奇奇怪怪的问题,不分时间,不分地点的出现崩溃。从调用堆栈来看,基本都是使用lua造成的。在多线程中使用lua_newthread得到的lus_State仍然有时候程序会崩溃。基本上可以确定为多线程中操作lua 的问题了。

前几天我转载的一篇文章,文章写了关于lua多线程的作法。作法有二

1.每一个线程函数用lua_newthread产生一个新的lua_state 以后对lua操作都用这个lua_state

2.修改lua源码使之成为支持多线程的(修改lua 源代码中lua_lock lua_unlock宏)

对于第2条,那篇文中的例子是用 pthread_mutex_t 来进行线程同步的pthread_mutex_t,我对pthread_mutex_t 不熟,网上一查才知道一般是在linux下C语言进行线程同步用的,在windows下面一般多线程都用CRITICAL_SECTION,和内核对象来进行线程同步的。于是产生了这篇文章。

修改代码如下:

1.global_State加一个成员变量  m_cs

Code Snippet
  1. typedef struct global_State {
  2.   stringtable strt;  /* hash table for strings */
  3.   lua_Alloc frealloc;  /* function to reallocate memory */
  4.   void *ud;         /* auxiliary data to `frealloc' */
  5.   lu_byte currentwhite;
  6.   lu_byte gcstate;  /* state of garbage collector */
  7.   int sweepstrgc;  /* position of sweep in `strt' */
  8.   GCObject *rootgc;  /* list of all collectable objects */
  9.   GCObject **sweepgc;  /* position of sweep in `rootgc' */
  10.   GCObject *gray;  /* list of gray objects */
  11.   GCObject *grayagain;  /* list of objects to be traversed atomically */
  12.   GCObject *weak;  /* list of weak tables (to be cleared) */
  13.   GCObject *tmudata;  /* last element of list of userdata to be GC */
  14.   Mbuffer buff;  /* temporary buffer for string concatentation */
  15.   lu_mem GCthreshold;
  16.   lu_mem totalbytes;  /* number of bytes currently allocated */
  17.   lu_mem estimate;  /* an estimate of number of bytes actually in use */
  18.   lu_mem gcdept;  /* how much GC is `behind schedule' */
  19.   int gcpause;  /* size of pause between successive GCs */
  20.   int gcstepmul;  /* GC `granularity' */
  21.   lua_CFunction panic;  /* to be called in unprotected errors */
  22.   TValue l_registry;
  23.   struct lua_State *mainthread;
  24.   UpVal uvhead;  /* head of double-linked list of all open upvalues */
  25.   struct Table *mt[NUM_TAGS];  /* metatables for basic types */
  26.   TString *tmname[TM_N];  /* array with tag-method names */
  27.   CRITICAL_SECTION m_cs; /*windows mutithread */
  28. } global_State;

 

2.在lua_newstate加入初始化Critical_section的代码 InitializeCriticalSection(&g->m_cs);

Code Snippet
  1. LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
  2.   int i;
  3.   lua_State *L;
  4.   global_State *g;
  5.   void *l = (*f)(ud, NULL, 0, state_size(LG));
  6.   if (l == NULL) return NULL;
  7.   L = tostate(l);
  8.   g = &((LG *)L)->g;
  9.   L->next = NULL;
  10.   L->tt = LUA_TTHREAD;
  11.   g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
  12.   L->marked = luaC_white(g);
  13.   set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
  14.   preinit_state(L, g);
  15.   g->frealloc = f;
  16.   g->ud = ud;
  17.   g->mainthread = L;
  18.   g->uvhead.u.l.prev = &g->uvhead;
  19.   g->uvhead.u.l.next = &g->uvhead;
  20.   g->GCthreshold = 0;  /* mark it as unfinished state */
  21.   g->strt.size = 0;
  22.   g->strt.nuse = 0;
  23.   g->strt.hash = NULL;
  24.   setnilvalue(registry(L));
  25.   luaZ_initbuffer(L, &g->buff);
  26.   g->panic = NULL;
  27.   g->gcstate = GCSpause;
  28.   g->rootgc = obj2gco(L);
  29.   g->sweepstrgc = 0;
  30.   g->sweepgc = &g->rootgc;
  31.   g->gray = NULL;
  32.   g->grayagain = NULL;
  33.   g->weak = NULL;
  34.   g->tmudata = NULL;
  35.   g->totalbytes = sizeof(LG);
  36.   g->gcpause = LUAI_GCPAUSE;
  37.   g->gcstepmul = LUAI_GCMUL;
  38.   g->gcdept = 0;
  39.   InitializeCriticalSection(&g->m_cs);
  40.   for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
  41.   if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
  42.     /* memory allocation error: free partial state */
  43.     close_state(L);
  44.     L = NULL;
  45.   }
  46.   else
  47.     luai_userstateopen(L);
  48.   return L;
  49. }

3.在close_state 加入删除CriticalSection的代码 DeleteCriticalSection(&g->m_cs);

Code Snippet
  1. static void close_state (lua_State *L) {
  2.   global_State *g = G(L);
  3.   luaF_close(L, L->stack);  /* close all upvalues for this thread */
  4.   luaC_freeall(L);  /* collect all objects */
  5.   lua_assert(g->rootgc == obj2gco(L));
  6.   lua_assert(g->strt.nuse == 0);
  7.   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
  8.   luaZ_freebuffer(L, &g->buff);
  9.   freestack(L, L);
  10.   lua_assert(g->totalbytes == sizeof(LG));
  11.   DeleteCriticalSection(&g->m_cs);
  12.   (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
  13. }

4.修改lua_lock和lua_unlock宏如下

Code Snippet
  1. #ifndef lua_lock
  2. #define lua_lock(L) EnterCriticalSection(&(G(L)->m_cs))
  3. #define lua_unlock(L) LeaveCriticalSection(&(G(L)->m_cs))
  4. #endif

5.为了使用CRITICAL_SECTION我们比较通用的方法是包含头文件 windows.h,但包含后发现,lua库中的LoadString函数正好与windows  api LoadString同名。所以把lua库内部所使用的LoadString通通改为LUA_LoadString即可

修改完之后,在控制台写了四个线程一个一个主lua_state,四个线程使用lua_newthread得到的lua_state,没有再出现错误了。

windows lua 多线程 线程同步的更多相关文章

  1. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

  2. 多线程 - 线程同步锁(lock、Monitor)

    1. 前言 多线程编程的时候,我们不光希望两个线程间能够实现逻辑上的先后顺序运行,还希望两个不相关的线程在访问同一个资源的时候,同时只能有一个线程对资源进行操作,否则就会出现无法预知的结果. 比如,有 ...

  3. Java多线程——线程同步

    在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的 ...

  4. Java基础-多线程-③线程同步之synchronized

    使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程 ...

  5. Java多线程 - 线程同步

    多线程操作同一个对象时,容易引发线程安全问题.为了解决线程安全问题,Java多线程引入了同步监视器. 同步代码块 同步代码块语法格式如下: synchronized(obj){ //此处的代码即为同步 ...

  6. Java分享笔记:创建多线程 & 线程同步机制

    [1] 创建多线程的两种方式 1.1 通过继承Thread类创建多线程 1.定义Thread类的子类,重写run()方法,在run()方法体中编写子线程要执行的功能. 2.创建子线程的实例对象,相当于 ...

  7. python多线程--线程同步

    如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步. 使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire ...

  8. JAVA多线程线程同步问题

    线程同步 在多线程的编程环境下,可能看着没有问题的代码在运行几千上万或者更多次后,出现了一些看着很奇怪的问题,出现这样的问题的原因就是可能会有两个或者更多个线程进入了同一块业务处理代码中导致了判断失效 ...

  9. Windows编程之线程同步

    本笔记整理自:<Windows核心编程(第五版)> 目录 什么是线程同步 用户方式中的线程同步 原子访问:Interlocked系列函数 CRITICAL_SECTION:关键段 内核对象 ...

随机推荐

  1. HDU 6324.Problem F. Grab The Tree-博弈(思维) (2018 Multi-University Training Contest 3 1006)

    6324.Problem F. Grab The Tree 题目看着好难,但是题解说的很简单,写出来也很简单.能想出来就是简单的,想不出来就难(讲道理,就算是1+1的题目,看不出来就是难的啊). 和后 ...

  2. 洛谷 P2415 集合求和【数学公式/模拟】

    给定一个集合s(集合元素数量<=30),求出此集合所有子集元素之和. 输入输出格式 输入格式: 集合中的元素(元素<=1000) 输出格式: 和 输入输出样例 输入样例#1: 2 3 输出 ...

  3. ubuntu下如何查找某个文件的路径

    1.whereis 文件名 特点:快速,但是是模糊查找,例如 找 #whereis mysql 它会把mysql,mysql.ini,mysql.*所在的目录都找出来. 2.find / -name ...

  4. [BZOJ2655]calc(拉格朗日插值法+DP)

    2655: calc Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 428  Solved: 246[Submit][Status][Discuss] ...

  5. AOJ 2266 Cache Strategy(费用流)

    [题目链接] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2266 [题目大意] 有M个桶,N个球,球编号为1到N,每个球都有重量 ...

  6. POJ 1486 Sorting Slides(二分图匹配)

    [题目链接] http://poj.org/problem?id=1486 [题目大意] 给出每张幻灯片的上下左右坐标,每张幻灯片的页码一定标在这张幻灯片上, 现在问你有没有办法唯一鉴别出一些幻灯片 ...

  7. [CodeChef-DGTCNT]Chef and Digits

    题目大意: 若一个十进制数$x$(不含前导零)满足数码$i$恰好出现$t_i$次,则这个数是坏的,否则是好的.求区间$[L,R](1\le L,R\le10^{18})$中有多少好数. 思路: 显然可 ...

  8. java web定时任务---Timer

    写在前面: 在最近的项目中需要每天定时对数据库表进行查询,并完成相关数据的更新操作.首先让我想到的是Timer类,记得在一开始维护那个老系统的时候,开了个接口,也涉及到了定时的操作.下面就记录下大概的 ...

  9. iOS开发——使用Autolayout生成动态高度的TableViewCell单元格

    步骤一.TableViewCell中使用Autolayout 要点:Cell的高度必须在Constraints中指明,但不能定死,需要让内部由内容决定高度的View决定动态高度. 如UILabel设置 ...

  10. 静态html分页

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...