public
Last active

  • Download Gist
synchronizable.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.