Skip to content

Instantly share code, notes, and snippets.

@bbozo
Created March 20, 2013 07:10
Show Gist options
  • Save bbozo/5202858 to your computer and use it in GitHub Desktop.
Save bbozo/5202858 to your computer and use it in GitHub Desktop.
Why A.perform and A.new.perform aren't the same thing, from http://blog.codeclimate.com/blog/2012/11/14/why-ruby-class-methods-resist-refactoring/ - A.perform is not threadsafe (unless it calls A.new.perform, heh), B.perform is
All A outputs:
AA
A
AAAAAAAAAA
AAA
AAAA
AAAAA
AAAAAA
AAAAAAA
AAAAAAAA
AAAAAAAAA
All B outputs:
B
B
B
B
B
B
B
B
B
B
class A # class method approach
def self.perform
@counter ||= ''
@counter = @counter + 'A'
end
end
class B # instance method approach
def perform
@counter ||= ''
@counter = @counter + 'B'
end
end
threads = 10.times.map do
Thread.new do
Thread.current[:a] = A.perform
Thread.current[:b] = B.new.perform
end
end
threads.each(&:join)
# let's inspect outputs
puts "All A outputs:"
puts threads.map{ |t| t[:a] }
puts "All B outputs:"
puts threads.map{ |t| t[:b] }
@cameron-martin
Copy link

Yup, in the first case @counter refers to an instance variable of A (remember classes are objects too), whereas in the second example, @counter refers to an instance variable of an instance of B.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment