Skip to content

Instantly share code, notes, and snippets.

@stefanoc
Created November 17, 2008 14:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefanoc/25771 to your computer and use it in GitHub Desktop.
Save stefanoc/25771 to your computer and use it in GitHub Desktop.
require "thread"
module Synchronizable
def self.included(base)
base.send(:include, InstanceMethods)
base.send(:extend, ClassMethods)
end
module ClassMethods
def synchronized(meth)
__synchronized_class__.send(:alias_method, "#{meth}_without_mutex", meth)
__synchronized_class__.send(:define_method, "#{meth}_with_mutex") do |*args|
__mutex__.synchronize do
send("#{meth}_without_mutex", *args)
end
end
__synchronized_class__.send(:alias_method, meth, "#{meth}_with_mutex")
end
def __synchronized_class__
unless @__synchronized_class__
@__synchronized_class__ = Class.new(self)
const_set("Synchronized", @__synchronized_class__)
end
@__synchronized_class__
end
end
module InstanceMethods
def __mutex__
@__mutex__ ||= Mutex.new
end
end
end
if __FILE__ == $0
class Account
include Synchronizable
attr_reader :balance
def initialize
@balance = 0.0
end
def credit(amount)
@balance += amount
end
def debit(amount)
@balance -= amount
end
synchronized :credit
synchronized :debit
end
acct = Account::Synchronized.new
threads = []
1000.times do |i|
threads << Thread.new(acct) do |account|
account.credit(1)
end
end
threads.each { |thread| thread.join }
puts acct.balance
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment