<转>多线程中的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

时间: 2024-10-02 07:47:09

<转>多线程中的lua同步问题的相关文章

MFC多线程中使用事件同步中的事件是什么?

问题描述 MFC多线程中使用事件同步中的事件是什么? MFC多线程中使用事件同步中的事件是什么?和消息处理中的事件有什么异同?同步就是上锁么? 解决方案 用WaitForMultipleObjects WaitForSingleObjects函数 解决方案二: 用事件同步多线程

java多线程中使用同步那它和单线程有什么区别?

问题描述 如果在多线程中使用同步synchronized比如有100个线程,所有线程都要一个一个的执行,那这和单线程不是一样了吗?并且多线程同步的时候操作系统来回的检查锁的状态倒浪费了性能,我理解的是不是哪里不对啊,请知道的帮解答一下,还有就是关于同步有很多方法,是不是都一回事只要会一种就行啊比如我就知道在run里synchronized(obj)这样 解决方案 解决方案二:它们的目的是相同的,都可以很好控制程序执行流程:多线程是为了提高CPU的利用率,在某个线程高速缓存或者执行等待时,可以通知

Java多线程编程中synchronized线程同步的教程_java

0.关于线程同步 (1)为什么需要同步多线程?线程的同步是指让多个运行的线程在一起良好地协作,达到让多线程按要求合理地占用释放资源.我们采用Java中的同步代码块和同步方法达到这样的目的.比如这样的解决多线程无固定序执行的问题: public class TwoThreadTest { public static void main(String[] args) { Thread th1= new MyThread1(); Thread th2= new MyThread2(); th1.sta

java多线程中两个容器之间的同步

问题描述 java多线程中两个容器之间的同步 写了一个多线程的爬虫(对多线程不熟悉),但是每次队列中都有重复的元素,我把代码逻辑贴上来,大家帮我看一下,谢谢了: 在进程中: queue = LinkedBlockingQueue set = ConcurrentSkipListSet 在每个进程中使用了bfs bfs: while(!queue.empty()){ s = queue.poll() //...逻辑代码 set.add(s) //对s所有子状态扩展 for(son : s.sons

.NET中的多线程 使用锁进行同步 及 Task

.NET中的多线程使用Task ask可以说是ThreadPool的升级版,在线程任务调度,并行编程中都有很大的作用. 创建并且初始化Task 使用lambda表达式创建Task Task.Factory.StartNew(() => Console.WriteLine("Hello from a task!")); var task = new Task(() => Console.Write("Hello"));task.Start(); 用默认参数

(单例设计模式中)懒汉式与饿汉式在多线程中的不同

/*  目的:分析一下单例设计模式中,懒汉式与饿汉式在多线程中的不同!  开发时我们一般选择饿汉式,因为它简单明了,多线程中不会出现安全问题!  而饿汉式需要我们自己处理程序中存在的安全隐患,但是饿汉式的程序技术含量更高! */ /* class SinglePerson implements Runnable{    private static SinglePerson ss = new SinglePerson("hjz", 22);//恶汉式    private int ag

[C#学习]在多线程中如何调用Winform

问题的产生: 我的WinForm程序中有一个用于更新主窗口的工作线程(worker thread),但文档中却提示我不能在多线程中调用这个form(为什么?),而事实上我在调用时程序常常会崩掉.请问如何从多线程中调用form中的方法呢? 解答: 每一个从Control类中派生出来的WinForm类(包括Control类)都是依靠底层Windows消息和一个消息泵循环(message pump loop)来执行的.消息循环都必须有一个相对应的线程,因为发送到一个window的消息实际上只会被发送到

C# 如何让 多线程中每个线程间隔毫秒执行同一个方法?

问题描述 多线程的好处让效率提高很多倍,但是在某些情况下要求操作同一个方法的时候要求有间隔,这个间隔当然是毫秒级别的否则多线程的意义就体现不出来,本问题就是怎么让多线程中每个线程间隔毫秒执行同一个方法,测试代码如下:privatevoidbtnTest_Click(objectsender,EventArgse){TestManyThreadtest=newTestManyThread();test.Start();} 主要代码如下classTestManyThread{privatestati

java-Java多线程中产生声音的问题

问题描述 Java多线程中产生声音的问题 这个我的声音类, public class Sound extends JApplet{ boolean Baozha = false,Fire = false,Move = false; AudioClip tankMove = java.applet.Applet.newAudioClip(Sound.class.getClassLoader().getResource("sound/myTankMove.wav")); AudioClip