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] }
@timblair
Copy link

timblair commented Apr 2, 2014

Just found my way here from the Code Climate blog post, and wanted to point out that the difference in behaviour has nothing to do with thread-safety: in A you're updating a single, shared class variable, whereas in B you're creating a new instance every time which means using an empty "counter" each time.

You see exactly the same behaviour without the threading (other than that the results are guaranteed to be in-order):

a, b = [], []

10.times do
  a << A.perform
  b << B.new.perform
end

a #=> ["A", "AA", "AAA", "AAAA", "AAAAA", "AAAAAA", "AAAAAAA", "AAAAAAAA", "AAAAAAAAA", "AAAAAAAAAA"]
b #=> ["B", "B", "B", "B", "B", "B", "B", "B", "B", "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