Skip to content

Instantly share code, notes, and snippets.

@jiro4989
Last active July 16, 2021 16:22
Show Gist options
  • Save jiro4989/be9ccc23108803228ffb76d8d8ba9b80 to your computer and use it in GitHub Desktop.
Save jiro4989/be9ccc23108803228ffb76d8d8ba9b80 to your computer and use it in GitHub Desktop.
Nimでマルチスレッドで起動してスレッド間で変数を共有する
import asyncdispatch, json
import jester
var
v = "sushi"
router myrouter:
get "/":
{.gcsafe.}:
v.add("1")
resp %*{"status":"ok"}
proc main =
var settings = newSettings(port = Port(5000))
var jester = initJester(myrouter, settings = settings)
jester.serve()
when isMainModule:
main()
import os, threadpool
var
sharedVar = 1
v = "str"
proc heavyMethod1(): int =
echo "1: Start"
sleep(5000)
echo "1: End"
inc(sharedVar)
{.gcsafe.}:
v.add("test1")
return 5
proc heavyMethod2(): int =
echo "2: Start"
sleep(2000)
echo "2: End"
{.gcsafe.}:
v.add("test2")
return 20
var result1 = spawn heavyMethod1()
var result2 = spawn heavyMethod2()
sync()
echo ^result1
echo ^result2
echo sharedVar
echo v
# クラッシュしたコード
import os, threadpool
var
v = "str"
proc heavyMethod1(): int =
for i in 1..1000:
{.gcsafe.}:
v.add("1")
echo "thread 1: " & v
return 5
proc heavyMethod2(): int =
for i in 1..1000:
{.gcsafe.}:
v.add("2")
echo "thread 2: " & v
return 20
var result1 = spawn heavyMethod1()
var result2 = spawn heavyMethod2()
sync()
echo ^result1
echo ^result2
echo v
import os, threadpool
var
v = "str"
proc heavyMethod1(): int =
for i in 1..1000:
{.gcsafe.}:
v.add("1")
return 5
proc heavyMethod2(): int =
for i in 1..1000:
{.gcsafe.}:
v.add("2")
return 20
var result1 = spawn heavyMethod1()
var result2 = spawn heavyMethod2()
sync()
echo ^result1
echo ^result2
echo v
import os, threadpool
var
v = "str"
proc heavyMethod1(n: int): int =
for i in 1..1000:
{.gcsafe.}:
v.add($n)
return 5
for i in 1..100:
var result1 = spawn heavyMethod1(i)
sync()
echo v
import locks
var
thr: array[0..4, Thread[tuple[a,b: int]]]
L: Lock
proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
for i in interval.a..interval.b:
acquire(L) # lock stdout
echo i
release(L)
initLock(L)
for i in 0..high(thr):
createThread(thr[i], threadFunc, (i*10, i*10+5))
joinThreads(thr)
@jiro4989
Copy link
Author

multithreads2.nim のほうだとクラッシュした

@jiro4989
Copy link
Author

{.gcsafe.} プラグマ内でechoしたのが不味いっぽい。
echoするのを消したらクラッシュしなくなった。
標準出力に書き込むことの副作用の関係だろうか。

@jiro4989
Copy link
Author

multithreads3.nim ならクラッシュしなかった

@jiro4989
Copy link
Author

jiro4989 commented Jan 10, 2020

jester1.nimに対して以下のリクエストを送りつけたらクラッシュした。
内容としては、curlをバックグラウンドで1000回なげた。
echoしてなくてもクラッシュする場合があるっぽい。

for i in {1..1000}; do curl http://localhost:5000 & done

@jiro4989
Copy link
Author

multithreads4.nim はクラッシュした。引数からは値をわたせないのだろうか

@jiro4989
Copy link
Author

multithreads4.nim、 nim c --threads:on --gc:boehm で実行したらクラッシュしなかった。

@jiro4989
Copy link
Author

jester1.nim を同じ方法で実行したら処理の途中でOOMで死んだ。boehmって何なんだろう

@jiro4989
Copy link
Author

https://nim-lang.org/docs/threads.html にかかれていた threads モジュールのサンプルは動いた

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment