“instruction sets”. Parallelism: Programming as simultaneous execution of (possibly related) instruction sets. See Rob Pike: https://talks.golang.org/2012/waza.slide#1
/ Multicore execution possible Spawned Process can be any other executable (not necessarily Ruby based) OS Dependent functionality (e.g. fork is only on POSIX based OS, not Windows) Skipping code examples for Process in this presentation!
memory between threads (and source of many problems) MRI Ruby has Global Interpreter Lock (GIL) • Does NOT prevent concurrent execution: when a thread is blocking on IO, it releases the GIL so another thread can execute Ruby code. • DOES prevent parallel execution of threads: multiple threads will NOT run simultaneously on multiple cores
do |url| Thread.new do open(url){|f| p [f.base_uri.to_s, f.charset]} end end.map(&:join) #=>["http://www.example.com", "iso-8859-1"] #=>["http://www.google.com", "iso-8859-1"] #=>["http://www.kcruby.org", "utf-8"]
Scheduling (programmer’s responsibility) Shared memory between Fibers Affected by GIL Light weight threads (you can create 100 K fibers but not as many threads)
Fiber 1" Fiber.yield end fiber2 = Fiber.new do puts "In Fiber 2" fiber1.transfer puts "Never see this message" end fiber2.resume #=> In Fiber 2 #=> In Fiber 1
When shared between concurrent Ruby blocks (a.k.a. goroutines) they provide a communication mechanism for coordinating asynchronous actions. They are thread safe and naturally concurrent.
'ping' end msg = messages.take puts msg # Ordering of .put and .take is important Concurrent::Channel.go do puts chan.take end chan.put 'pong' puts "-- done --"
at some time in the future. The action (promise.value) is atomic and permanent. The idea behind a future is to send an operation for asynchronous completion, do other stuff, then return and retrieve the result of the async operation at a later time. Futures run on the global thread pool.
'open-uri' # for open(uri) class Ticker def get_year_end_closing(symbol, year) uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year }&g=m" data = open(uri) {|f| f.collect{|line| line.strip } } data[1].split(',')[4].to_f end end
Like a fiber, it is non preemptive. Unlike thread or fiber there is no shared memory. Message passing between two actors. It has a mailbox and a routine named “receive” to check its mailbox for new messages.
'first'. # Return value is a reference to the actor, the actual actor is never returned. counter = Counter.spawn(:first, 5) # Tell a message and forget returning self. counter.tell(1) counter << 1 # Send a messages asking for a result. p counter.ask(0).value