lua_newthread的真正意义

 

lua_newthread 这个接口,存在误导性,很多人第一次试图用它来解决多线程问题时,都会入坑。

 

实际上,这个接口真正的用法,是给那些在lua更底层的某些行为(通常是递归)导致了lua的栈溢出而准备的。

举例说明:

我在C底层实现了重新开始这种功能,并且我将这种功能暴露给lua了,lua在某些适当的时机,会调用restart();

restart的实现大概如下:

static int restart(lua_State *s){

    longjmp(rem, 0);

    return 0;

}

使用了setjmp和longjmp来进行远跳,这种时候,实际上,lua的调用栈就存在问题了,

不管脚本内容是什么样的,总之从C不管以任何形式进入lua虚拟机之后再到C函数restart,这之间由lua诞生的各种垃圾内存,由于没有正常返回,而不能被lua的垃圾收集器正确回收。

随着这种行为的次数增加到一定程度,在某次进入lua vm之后,就会报栈溢出。

 

而要解决这种问题的关键,就是lua_newthread

 lua_newthread的意义是新建一个调用栈,这个调用栈与某个lua vm对象共享全局环境,它本身和线程没有关系,默认的情况下,它不能解决并发问题。

解决方案如下:

s = lua_newthread(source);
lua_setglobal(source, "___safe_thread_vm_"); -- 将调用栈记录到全局变量
lua_gc(source, LUA_GCCOLLECT); -- 垃圾回收,上一次的调用栈,会在此时被完全回收。

source就是主对象,也就是由luaL_newstate正常创建的lua对象,加载文件,初始化什么的,都由它在程序一开始的时候处理好,在之后进入虚拟机都是 s

 

posted @ 2020-03-19 22:29  babypapa  阅读(2565)  评论(0编辑  收藏  举报