In Ruby, I'm used to seeing puts always append a newline to the string being printed before printing it.
While playing around with multi-threading in Ruby, including running it with JRuby, I noticed some odd behavior. Sometimes, two lines will be printed on the same line instead of being printed on separate lines like I expected. In my first time trying this, my script was using a Semaphore from concurrent-ruby because I was testing out concurrency and parallelism patterns. I was using the semaphore to only allow a configured number of threads from being started at a time. It was about a 20% chance of it happening.
To create a minimal reproduction for Stack Overflow, I took out concurrent-ruby and created a smaller version of my program that just created threads that ran immediately, without first storing the blocks of code in procs and without using a semaphore. With this new program, this issue happens 100% of the time (at least for how many times I've tried running it so far).
I understand that with multi-threading, the order of the two lines being printed could be different each time, depending on which thread runs first. But I didn't expect that sometimes, the newline that should be on the end of every string printed (because I print them with puts) would sometimes not be there.
Program:
def work(n)
puts "Started unit of work ##{n}."
i = 0
100000000.times { i += 1 }
puts "Finished unit of work ##{n}."
end
threads = []
2.times do |i|
thread = Thread.new do
work(i + 1)
end
threads << thread
end
threads.each do |t|
t.join
end
puts "\nEnd."
Output:
Started unit of work #1.Started unit of work #2. Finished unit of work #2. Finished unit of work #1. End.
Note how the output includes Started unit of work #1.Started unit of work #2. and not Started unit of work #1.\nStarted unit of work #2.. Also note how this issue doesn't occur for the second call to puts in each thread. Those are on separate lines, as expected.
This output was consistent every time I ran the Ruby script with JRuby. I couldn't get a run where it printed a newline after Started unit of work #1. or Started unit of work #2..
System details:
> jruby --version jruby 9.3.8.0 (2.6.8) 2022-09-13 98d69c9461 OpenJDK 64-Bit Server VM 19+36-2238 on 19+36-2238 +jit [x86_64-linux]
> java --version openjdk 19 2022-09-20 OpenJDK Runtime Environment (build 19+36-2238) OpenJDK 64-Bit Server VM (build 19+36-2238, mixed mode, sharing)
> lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.1 LTS Release: 22.04 Codename: jammy