(转)Lua语言实现简单的多线程模型
转自: https://blog.csdn.net/john_crash/article/details/49489609
lua本身是不支持真正的多线程的,但是lua提供了相应的机制来实现多线程。lua执行在一个lua环境中内部叫lua_State。如果我们创建多个lua_State,并且创建一一对应的线程来启动它就基本实现了一个封闭的多线程环境。但是这种环境下lua代码之间没有任何联系,不能共享数据,不能进行同步。因此我们需要建立一套共享数据与同步的机制来。
thread.new("test_thread")
--另一个文件test_thread.lua
local function proc()
print("hello world")
end
return proc
- 1
- 2
- 3
- 4
- 5
- 6
- 7
上面的例子代码主线程中执行thread.new(“test_thread”)创建一个新的线程,同时创建一个lua_State,在这个lua环境中装入test_thread.lua并启动它返回的函数proc。用c代码为lua实现这样的一个线程库并不难。大概步骤是先创建线程,然后在线程中创建lua_State,这可以使用luaL_newstate()来完成。然后为新环境初始化默认库luaL_openlibs(L)可以完成这个工作,随后你可以注册你的函数与库。以便在这个独立线程可以调用这些库。
下面考虑为thread.new加入更多的参数,第一参数用来指定线程启动的脚本文件,第二参数用来指定一个回调函数,后面依次是传递给线程函数的参数。并且为线程提供两个3个函数。post,wait,sleep。
post用来回调主线程的回调函数,wait用来阻塞线程等待主线程的通知,sleep休眠一段时间。
为线程对象提供一个函数notify用来通知等待线程继续执行。
例子1
thread.new("test",1,2)
--test.lua
return function(arg1,arg2)
print(arg1..","..arg2)
end
- 1
- 2
- 3
- 4
- 5
这里例子用来启动一个线程并且传输两个参数,1,2。程序打印1,2
例子2
thread.new("test")
--test.lua
return function()
print("hello")
sleep(1000)
print("world")
end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这里例子先打印hello然后等待1秒在打印world
例子3
local t = thread.new("test")
sleep(1000)
local b,p1,p2 = t.notify("hello","world")
--test.lua
return function()
local b,p1,p2 = wait("hi","main thread")
print(p1..","..p2)
end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
这个例子线程启动后,主线程等待1秒,线程起来调用wait等在哪里,当主线程调用notify时,wait返回notify的参数”hello”,”world”,而notify返回wait的参数”hi”,”main thread”。注意wait第一参数是一个布尔值,当成功和notify交互数据时为true否则是false,并且下一个返回值是一个错误提示字符串。程序打印hello,world。
程序可以通过notify,wait对来进行交互数据,并进行同步。
例子4
local t = thread.new("test",function(p)
print(p)
return "done"
end,"hello","world")
--test.lua
return function(p1,p2)
print(p1..","..p2)
local b,r = post("hi")
print(r)
end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
例子展示线程使用post向主线程函数发送消息,首先主线程创建一个线程,并传递参数”hello”,world”,线程先打印hello world,然后它调用post向主线程发消息”hi”,主线程接收到并打印”hi”,并且返回”done”,然后线程打印done完成整个过程。两个线程在post这个函数是同步的,并且交互数据。
这个模型包括很少的函数,它能然lua具有一定的线程能力。
线程对象创建函数
thread.new( module,callback,… )
module指定一个lua文件名,callback一个回调,用来响应线程中post函数。后面可以跟任意多个参数。这些参数将被传输到module返回的函数中。thread.new返回成功返回一个线程对象,失败返回nil,加一个错误字符串。
线程对象有两个函数和一些状态。
obj:notify(…)
notify用来通知线程中的wait继续执行,并与wait交互参数。notify成功返回true,后面跟wait传输的参数。失败返回nil,加一个错误字符串。
obj:join()
阻塞调用线程指定线程对象结束。
线程对象具有一个属性.state 可以是下面的值
“init”,线程还在启动过程中
“run”,线程真正执行
“wait”,线程处于wait阻塞状态
“exit”,线程已经退出
在线程内部可以调用下列函数。
sleep(ms) 休眠多少毫秒
wait(…) 线程阻塞,并将参数传递给唤醒它的主线程,成功返回true加notify的参数,失败返回nil,加一个错误字符串。
post(…) 向主线程的回调函数发送参数,成功将返回true,后面加回调函数的返回。,失败返回nil,加一个错误字符串。