CSC/ECE 517 Spring 2015/ch1a 14 RI: Difference between revisions
No edit summary |
No edit summary |
||
Line 44: | Line 44: | ||
We can see that threadsafe method consists of only 4 options. The first option @preload_frameworks describes how the application is loaded and ensure that the entire framework is preloaded instead of relying on auto-loading behavior which is not thread-safe. The second option @cache_classes tells Rails not to automatically reload classes when they are modified so to not waste resources. The third option @dependency_loading prevents Rails from loading code when missing constants are discovered, which is not thread safe. The last option is set to true and it tells Rails to not use Rack::Lock middleware, which ensures that only one thread executes at a time (synchronization). | We can see that threadsafe method consists of only 4 options. The first option @preload_frameworks describes how the application is loaded and ensure that the entire framework is preloaded instead of relying on auto-loading behavior which is not thread-safe. The second option @cache_classes tells Rails not to automatically reload classes when they are modified so to not waste resources. The third option @dependency_loading prevents Rails from loading code when missing constants are discovered, which is not thread safe. The last option is set to true and it tells Rails to not use Rack::Lock middleware, which ensures that only one thread executes at a time (synchronization). | ||
== Rack::Lock == | |||
Within Rails there is middleware called Rack, which essentially provides a uniform way for Ruby and Rails to work with web servers and frameworks such as Apache, Thin, etc. Within Rack there is an environment property rack.multithread. The Rack::Lock piece of Rack disables the rack.multithread flag, which means that the application will be allowed to serve multiple threads. When Rack::Lock is enabled within Rails (when threadsafe! is disabled), the application is only allowed one thread at a time. This serialization does ensure thread safety, but it does so at the expense of run time, because if only one thread can execute at a time, then the other threads must wait for every thread before it to finish. This defeats the purpose of a threaded webserver, which is a necessity in today's Web. | |||
== Rails 4.0 == | == Rails 4.0 == | ||
Revision as of 01:00, 7 February 2015
Thread Safety
A multi-threaded program presents the risk of race conditions, which are situations in which multiple threads rely on the same system state. This is a dangerous situation because if multiple threads access the same state simultaneously, the state could become corrupted. Thread safety avoids race conditions by guaranteeing that multiple threads can run safely, concurrently.
Background
A thread is a small set of instructions that can be handled independently by the scheduler. Multithreading is the concept of allowing multiple threads within the execution of a single process, which allows those threads to share resources. Multithreading is a useful and powerful construct within web-server environments, such as rails. For example, multiple threads could be used to handle requests from multiple users simultaneously, while also handling long running tasks in the background. As a result of multithreading, users have a better experience, because tasks that would pause execution in a single threaded application, can be allotted their own thread, and the user is never interrupted. Although having multiple threads is powerful, it is equally dangerous, due to race conditions. Race conditions occur when multiple threads are accessing the same state, most specifically the same data, and thus the output depends on the correct order of operations, but the threads execute out of order, causing the data to be corrupted. Thus, thread safety ensures that when multiple threads alter shared components, they do so in a guaranteed safe manner, therefore there will be no race conditions within a thread safe application.
Race Condition Example
The following is example of code that, if included in a non thread safe context, could lead to race conditions:
1: def raceCondition (param, check) 2: if param.eql?(check) 3: param += 2 4: end 5: end
Line 1 is simply defining the method and taking in two parameters: param and check. Line 2 then checks to see if param is equal to check, if so in Line 3 2 is added to param. This method introduces a possible race condition because of the read, then update nature. If multiple threads were running simultaneously and in between Thread A running Line 2 and Line 3, Thread B changes the value of param, then param will not receive the anticipated value (check + 2) at Line 3 of Thread A. In a critical environment, a race condition like this could have serious negative effects on a production database, which is why having thread safe applications is of utmost importance.
History
Multithreading is not a new concept to Rails. Previous versions of Rails were capable of supporting multithreading in the applications very effectively. In the previous versions of Rails, once an application template was created, a programmer could find a method named "threadsafe!" in the configurations and enable it for multithreaded applications. This option used to be located in the production.rb file located on the generic path config/environments/production.rb. Therefore, this option for multithreading was automatically disabled (commented out in the configuration file) in the previous versions of Rails and the programmers always had to manually enable it to make their application thread-safe.
Manually Enabling Multithreading
In order to manually enable multitreading, in versions of Ralis prior to 4.0, the following source code of threadsafe! methodsimply needed to be un-commented out:
def threadsafe! @preload_frameworks = true @cache_classes = true @dependency_loading = false @allow_concurrency = true self end
We can see that threadsafe method consists of only 4 options. The first option @preload_frameworks describes how the application is loaded and ensure that the entire framework is preloaded instead of relying on auto-loading behavior which is not thread-safe. The second option @cache_classes tells Rails not to automatically reload classes when they are modified so to not waste resources. The third option @dependency_loading prevents Rails from loading code when missing constants are discovered, which is not thread safe. The last option is set to true and it tells Rails to not use Rack::Lock middleware, which ensures that only one thread executes at a time (synchronization).
Rack::Lock
Within Rails there is middleware called Rack, which essentially provides a uniform way for Ruby and Rails to work with web servers and frameworks such as Apache, Thin, etc. Within Rack there is an environment property rack.multithread. The Rack::Lock piece of Rack disables the rack.multithread flag, which means that the application will be allowed to serve multiple threads. When Rack::Lock is enabled within Rails (when threadsafe! is disabled), the application is only allowed one thread at a time. This serialization does ensure thread safety, but it does so at the expense of run time, because if only one thread can execute at a time, then the other threads must wait for every thread before it to finish. This defeats the purpose of a threaded webserver, which is a necessity in today's Web.
Rails 4.0
Beginning with Rails version 4.0 multithreading has been automatically enabled and supported by the initial configuration. The threadsafe method has been removed from the configuration file and it cannot be found in the production.rb file anymore. This enables Rails 4.0 to automatically provides thread safety to all of its applications. The authors of this wiki page believe that the main reason for this approach has been to make learning rails more beginner-friendly and eliminate corruption of Rails applications written by inexperienced programmers.
References
http://www.sitepoint.com/config-threadsafe/
http://en.wikipedia.org/wiki/Thread_(computing)
http://en.wikipedia.org/wiki/Race_condition
http://en.wikipedia.org/wiki/Thread_safety
http://weblog.rubyonrails.org/2013/6/25/Rails-4-0-final/
http://guides.rubyonrails.org/configuring.html
http://tenderlovemaking.com/2012/06/18/removing-config-threadsafe.html