コルーチンとは何ですか?
Lua コルーチンはスレッドに似ています。独立したスタック、独立したローカル変数、独立した命令ポインターを持ち、グローバル変数やその他のほとんどのものを他のコルーチンと共有します。
コラボレーションは非常に強力な機能ですが、使い方が非常に複雑でもあります。
スレッドとコルーチンの違い
スレッドとコルーチンの主な違いは、複数のスレッドを持つプログラムは複数のスレッドを同時に実行できるのに対し、コルーチンは相互に連携して実行する必要があることです。
常に 1 つのコルーチンのみが実行され、実行中のコルーチンは明示的に一時停止するように要求された場合にのみ一時停止されます。
コルーチンは同期されたマルチスレッドに似ており、同じスレッド ロックを待機する複数のスレッドはコラボレーションに似ています。
基本構文
メソッド | 説明 |
---|
coroutine.create() | コルーチンを作成し、コルーチンを返します。パラメータは関数であり、再開と一緒に使用すると、関数呼び出しを起動します |
coroutine.resume() | コルーチンを再起動し、create |
coroutine.yield() で使用します | コルーチンを一時停止し、コルーチンを一時停止状態に設定します。これは、resume |
と組み合わせて使用すると、多くの便利な効果が得られます。 coroutine.status() | コルーチンの状態を確認します 注: コルーチンにはデッド、サスペンド、実行中の3つの状態があります。このような状態が発生した場合については、以下のプログラムを参照してください |
coroutine.wrap( ) | コルーチンを作成して関数を返す この関数を呼び出したら、create関数を繰り返してコルーチンに入ります |
coroutine.running() | runningを使用する場合、コルーチンはスレッドです。 、コルーティング スレッド番号を返します |
以下の例は、上記の各メソッドの使用法を示しています:
-- coroutine_test.lua 文件
co = coroutine.create(
function(i)
print(i);
end
)
coroutine.resume(co, 1) -- 1
print(coroutine.status(co)) -- dead
print("----------")
co = coroutine.wrap(
function(i)
print(i);
end
)
co(1)
print("----------")
co2 = coroutine.create(
function()
for i=1,10 do
print(i)
if i == 3 then
print(coroutine.status(co2)) --running
print(coroutine.running()) --thread:XXXXXX
end
coroutine.yield()
end
end
)
coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3
print(coroutine.status(co2)) -- suspended
print(coroutine.running())
print("----------")
上記の例の実行出力は次のとおりです:
1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868 false
suspended
thread: 0x7fb801c04c88 true
----------
coroutine.running コルーチンの基礎となる実装がスレッドであることがわかります。
コルーチンを作成すると、新しいスレッドにイベントが登録されます。
resume を使用してイベントをトリガーすると、create のコルーチン関数が実行されます。yield が発生すると、現在のスレッドが一時停止され、イベントが再度トリガーされるのを待機することになります。
次に、より詳細な例を分析します:
function foo (a)
print("foo 函数输出", a)
return coroutine.yield(2 * a) -- 返回 2*a 的值
end
co = coroutine.create(function (a , b)
print("第一次协同程序执行输出", a, b) -- co-body 1 10
local r = foo(a + 1)
print("第二次协同程序执行输出", r)
local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入
print("第三次协同程序执行输出", r, s)
return b, "结束协同程序" -- b的值为第二次调用协同程序时传入
end)
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")
上記の例の実行出力結果は次のとおりです:
第一次协同程序执行输出 1 10
foo 函数输出 2
main true 4
--分割线----
第二次协同程序执行输出 r
main true 11 -9
---分割线---
第三次协同程序执行输出 x y
main true 10 结束协同程序
---分割线---
main false cannot resume dead coroutine
---分割线---
上記の例は次のように続きます:
resume を呼び出してコルーチンを起動し、再開操作が返されます。成功した場合は true、そうでない場合は false を返します。
コルーチンが実行され、最初の再開が返されます。は再開のパラメータです)
2 回目に再開し、再びコルーチンを起動します (注: ここでの再開パラメータのうち、最初のパラメータを除く残りのパラメータは、yield パラメータとして使用されます)
yield returns;
-
コルーチンは実行を継続します
使用されたコルーチンが実行を継続し、完了後に再開メソッドを呼び出し続ける場合、出力は次のようになります: 停止したコルーチンを再開できません
resume と yield は、レジュームがメイン プロセス内にあり、外部状態 (データ) をコルーチンに渡し、yield は内部状態 (データ) をメイン プロセスに返します。
- プロデューサー-コンシューマー問題ここで、Lua のコルーチンを使用して、古典的なプロデューサー-コンシューマー問題を解決します。
local newProductor
function productor()
local i = 0
while true do
i = i + 1
send(i) -- 将生产的物品发送给消费者
end
end
function consumer()
while true do
local i = receive() -- 从生产者那里得到物品
print(i)
end
end
function receive()
local status, value = coroutine.resume(newProductor)
return value
end
function send(x)
coroutine.yield(x) -- x表示需要发送的值,值返回以后,就挂起该协同程序
end
-- 启动程序
newProductor = coroutine.create(productor)
consumer()
上記の例の実行出力結果は次のとおりです: 1
2
3
4
5
6
7
8
9
10
11
12
13
……