220 likes | 371 Views
CSC407: Software Architecture Summer 2006 Design Patterns III. Greg Wilson BA 4234 gvwilson@cs.utoronto.ca. Concurrency Patterns. Programming is hard Concurrent programming is a zillion times harder People aren’t good at thinking about many things at once
E N D
CSC407: Software ArchitectureSummer 2006Design Patterns III Greg Wilson BA 4234 gvwilson@cs.utoronto.ca
Concurrency Patterns • Programming is hard • Concurrent programming is a zillion times harder • People aren’t good at thinking about many things at once • Race conditions make bugs intermittent • But concurrency is what’s going to keep us on Moore’s Curve • Every processor and system you care about already does many things at once
…Concurrency Patterns • Makes the use of design patterns even more important • Every pattern is the distilled experience of dozens of your predecessors • Where “experience” is what we call our mistakes when we’re in a job interview • Nothing wrong with inventing entirely new solutions from scratch, as long as you have time to debug them
Active Object • An active object has its own thread of execution • Instead of “calling methods”, other objects “send messages” • The latter terminology is sometimes used for regular objects as well • Must make sure that some messages are only accepted under the right conditions • E.g., only print jobs one at a time • The basis of many other patterns
Reactor • Problem: want to wait for any of several different events of different kinds • E.g., incoming socket connection or timeout or signal • Solution: spawn one child for each different kind of event • Most OS’s can multiplex events of a single kind • Children all communicate with parent in the same way • An example of the Adapter pattern
Leader/Follower • Problem: the more inter-thread communication you have, the less efficient your system is • Having one thread wait for connections, then pass requests to other threads that talk to the database, is probably OK • Doing this in a real-time system may not be • Solution: threads take turns being the leader or followers • A two-state state machine
Thread Pool and Task Farm • The preceding diagram refers to a Thread Pool • Another design pattern • Name explains itself… • Sometimes used as a synonym for Task Farm • We will use the latter to mean a system with: • A source that generates jobs • A pool of workers that execute them • A sink that collects results
…Task Farm • The preceding diagram refers to a Thread Pool • Another design pattern • Name explains itself… • Sometimes used as a synonym for Task Farm • We will use the latter to mean a system with: • A source that generates jobs • A pool of workers that execute them • A sink that collects results
…Task Farm • One of the few models for massively parallel computing that actually works • Seen any good movies lately? • “Commodity computing” is a recurring hot topic • Major obstacles are security and privacy
SIMD • Single Instruction, Multiple Data • I.e., apply a single instruction to many values at once • At the hardware level, can be implemented by: • Pipelining (your GPU) • Lots of Little Processors (LOLP) • Also makes sense as a programming model • MATLAB, anyone?
…SIMD • The other massively parallel programming model that people can actually understand • I.e., debug • But what do you do about conditionals? # Get absolute value of A Array[zillion, zillion] A where A < 0: A = -A
…SIMD • What about function calls? where A < 0: A = f(A) • If mask is inherited, author of f() has no idea which writes will take effect • If mask is not inherited, caller of f() has no idea what values will be mutated
Yes, This Is Really Hard • Problem: want to initialize data safely in a multithreaded program class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) { helper = new Helper(); } return helper; } }
…Really Hard class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) { helper = new Helper(); } } } return helper; } }
…Really Hard • But the compiler may assign a value to helper before it has finished constructing the object • Second thread to come along sees a non-null reference, and assumes the object is good to use • Go ahead—try to debug this… • Java 1.4 solution: synchronize getHelper() • And take the 100X performance hit • Java 1.5 solution: use the volatile keyword
Summary • Knowing lots of design patterns won’t make you a great programmer • But it can stop you from being a bad one • See c2.com/cgi/wiki?PortlandPatternRepository (the original wiki) • Buy a book! • Gang of Four started it all • Metsker’s and Grand’s are my favorites