Question when spawning a fiber

I test this code in https://crystal-lang.org/reference/guides/concurrency.html

i = 0
while i < 10
  spawn do
    puts(i)
  end
  i += 1
end

Fiber.yield

the document say The above program prints "10" ten times, but I got this:

2
3
10
10
10
10
10
10
10
10
$crystal --version
Crystal 0.31.1 [0e2e1d067] (2019-09-30)

LLVM: 8.0.0
Default target: x86_64-unknown-linux-gnu

$cat /etc/centos-release 
CentOS Linux release 7.7.1908 (Core) ## 64bit

That’s very unexpected. Does it repeat in exactly the same manner?

My first guess would be that the -Dpreview_mt flag is on. But in that case it might not even print 10 numbers because the main fiber exits before all of the others have executed.

The example needs to be changed anyway, because the scheduler does not guarantee an execution order for fibers, but the example expects the main fiber to be resumed only after all other fibers have been executed.

1 Like

For me it prints “10” all the time.

Regardless of this, the idea of the explanation is to make it clear that i is just a single variable that will be shared across all spawn invocations and you can’t rely on it being 1, 2, etc., for each spawn. The docs are overspecifying what happens: it could be what you saw or it could be all 10. Maybe that should be made clear in the docs.

1 Like

yes, I forget to say I add -Dpreview_mt when build,

$cat test.cr
i = 0
while i < 10
  spawn do
    puts(i)
  end
  i += 1
end

Fiber.yield

$crystal build test.cr --release -Dpreview_mt
$export CRYSTAL_WORKERS=2;./test
4
6
6
7
10
10
10
10
10
10
$export CRYSTAL_WORKERS=1;./test
10
10
10
10
10
10
10
10
10
10

With CRYSTAL_WORKERS > 1 this is totally expected.

We’ll eventually need to review and update documentation for changes introduced by multithreading. But currently, it’s only a preview feature and not stable. So there’s no point in acting right now.

2 Likes