Ruby | Introduction to Multi-threading
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 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 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
Please Login to comment...