Ruby | Introduction to Multithreading (original) (raw)

Ruby | Introduction to Multi-threading

Last Updated : 18 Sep, 2018

Multi-threading is the most useful property of Ruby which allows concurrent programming of two or more parts of the program for maximizing the utilization of CPU. Each part of a program is called Thread. So, in other words, threads are lightweight processes within a process. An ordinary program contains single thread and all the statements or instructions are executed sequentially. But a multi-threaded program contains more than one thread and within each thread statements or instructions execute sequentially, but the thread itself executes concurrently on the multi-core processor. Multi-threading reduces the memory usage as compared to a single thread by performing multiple tasks. Before Ruby 1.9, threads were switched within the interpreter which are termed as Green Threads. But from Ruby 1.9 onwards, threading is performed by the operating system. The two threads running in the same Ruby application can never be truly concurrent. In Ruby, a multi-threaded program is created with the help of Thread class and a new thread is created by calling a block, i.e Thread.new.

Creating Threads in Ruby

In Ruby, creating a new thread is very easy. There are three blocks (Thread.new, Thread.start, or Thread.fork) by which you can create a thread in a program. Generally, Thread.new is used to create the thread. Once the thread created, the original thread will return from one of these Thread creation blocks and resume the execution with the next statement.Syntax:

Original thread is running

creating thread

Thread.new { # new thread runs here }

Outside the block

Original thread is running

Example:

Ruby `

Ruby program to illustrate

creation of threads

#!/usr/bin/ruby

first method

def Geeks1 a = 0 while a <= 3

   puts "Geeks1: #{a}"

  # to pause the execution of the current
  # thread for the specified time
  sleep(1)

  # incrementing the value of a
  a = a + 1

end

end

Second method

def Geeks2 b = 0

while b <= 3

   puts "Geeks2: #{b}"

  # to pause the execution of the current
  # thread for the specified time
  sleep(0.5)

  # incrementing the value of a
  b = b + 1

end

end

creating thread for first method

x = Thread.new{Geeks1()}

creating thread for second method

y= Thread.new{Geeks2()}

using Thread.join method to

wait for the first thread

to finish

x.join

using Thread.join method to

wait for the second thread

to finish

y.join

puts "Process End"

`

Output:

Geeks1: 0 Geeks2: 0 Geeks2: 1 Geeks1: 1 Geeks2: 2 Geeks2: 3 Geeks1: 2 Geeks1: 3 Process End

Note: Output may be different as resources to threads are allocated by the operating system.

Terminating Threads

When a Ruby program is terminated, all the threads related to that program is also killed. A user can kill the threads using class ::kill.Syntax:

Thread.kill(thread)

Thread variables and their Scope

As threads are defined by the blocks so they have access to local, global and instance variables which are defined in the scope of the block. Variables present in the block of the thread are the local variables for that thread and they are not accessed by any other thread block. Thread class allows a thread-local variable to be created and accessed by their name. If two or more threads wants to read and write the same variable concurrently then there must be thread synchronization. Example:

Ruby `

Ruby program to illustrate

Thread variables

#!/usr/bin/ruby

Global variable

$str = "GeeksforGeeks"

first method

def Geeks1

only access by Geeks1 Thread

a = 0

while a <= 3

   puts "Geeks1: #{a}"

  # to pause the execution of the current
  # thread for the specified time
  sleep(1)

  # incrementing the value of a
  a = a + 1

end

accessing str

puts "Global variable: #$str"

end

Second method

def Geeks2

only access by Geeks2 Thread

b = 0

while b <= 3

   puts "Geeks2: #{b}"

  # to pause the execution of the current
  # thread for the specified time
  sleep(0.5)

  # incrementing the value of a
  b = b + 1

end

accessing str

puts "Global variable: #$str"

end

creating thread for first method

x = Thread.new{Geeks1()}

creating thread for second method

y= Thread.new{Geeks2()}

using Thread.join method to

wait for the first thread

to finish

x.join

using Thread.join method to

wait for the second thread

to finish

y.join

puts "Process End"

`

Output:

Geeks1: 0 Geeks2: 0 Geeks2: 1 Geeks1: 1 Geeks2: 2 Geeks2: 3 Geeks1: 2 Global variable: GeeksforGeeks Geeks1: 3 Global variable: GeeksforGeeks Process End