According to this answer they are, but then the poster states that things work differently in JRuby so I am confused?
I am implementing a multi tenancy solution using class instance variables, so it doesn't matter what Ruby implementation or web server I am using, I need to make sure that data cannot be leaked.
Here is my code:
class Tenant < ActiveRecord::Base
def self.current_tenant=(tenant)
@tenant = tenant
end
def self.current_tenant
@tenant
end
end
What do I need to do to make sure that no matter what happens (changing Ruby implementation, changing web server, new Ruby threading capabilities etc) that my code is thread safe?
It is because, Servlets create only one instance and multiple threads access it. So in that case Instance Variables are not thread safe.
Performing writes/reads on class variables in Ruby is not thread safe. Performing writes/reads on instance variables appears to be thread safe.
What is the difference between class variables and class instance variables? The main difference is the behavior concerning inheritance: class variables are shared between a class and all its subclasses, while class instance variables only belong to one specific class.
Static variables are not thread safe. Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.
Since the tenancy attribute's scope is a request, I would suggest you keep it in the scope of the current thread. Since a request is handled on a single thread, and a thread handles a single request at a time - as long as you always set the tenancy at the beginning of the request you will be fine (for extra security, you might want to un-assign the tenant at the end of the request).
To do this you can use thread local attributes:
class Tenant < ActiveRecord::Base
def self.current_tenant=(tenant)
Thread.current[:current_tenant] = tenant
end
def self.current_tenant
Thread.current[:current_tenant]
end
def self.clear_current_tenant
Thread.current[:current_tenant] = nil
end
end
Since this is using a thread store, you are totally thread safe - each thread is responsible for its own data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With