We plan to study the entire book in order, somtimes combining two
		sections into a single session, sometimes splitting a section over two
		sessions.
 
	  
		 
		  | 1.1 Using Concurrency Constructs
			 (1-18) | Session 1 | 
 
		 
		  | Introduces the basic
			 Java concurrency support constructs and the principal methods of class
			 Thread. | 
 
		 
		  | 1.2 Objects and Concurrency
			 (19-36) |  | 
 
		 
		  | Describes the primary
			 uses of concurrency, the basic units used to implement concurrent execution,
			 and how these map onto object models. | 
 
		 
		  | 1.3 Design Forces (37-56) | Session 2 | 
 
		 
		  | Surveys the design concerns that arise in
			 concurrent software development, including safety, liveness, performance, and
			 reusability. | 
 
		 
		  | 1.4 Before/After Patterns
			 (57-68) | Session 3 | 
 
		 
		  | Discusses the primary
			 design patterns used to implement symmetrical control mechanisms. | 
 
		 
		  | 2.1 Immutability (69-74) | Session 4 | 
 
		 
		  | Discusses the uses of immutable and
			 partially immutable objects in concurrent programs. | 
 
		 
		  | 2.2 Synchronization (75-98) |  | 
 
		 
		  | Discusses the serialized execution of
			 synchronized Java threads and the impact they have on objects. | 
 
		 
		  | 2.3 Confinement
			 (99-116) | Session 5 | 
 
		 
		  | Discusses encapsulation
			 techniques that structurally guarantee that only a single thread will ever
			 access some object(s) at a given time. | 
 
		 
		  | 2.4 Structuring and Refactoring Classes
			 (117-146) | Sessions 6 + 7 | 
 
		 
		  | Discusses strategies for removing
			 unnecessary synchronization, synchronization splitting, read-only operation
			 export, state isolation, and lock reuse. | 
 
		 
		  | 2.5 Using Lock Utilities
			 (147-158) | Session 8 | 
 
		 
		  | Discusses the
			 implementations of commonly used lock utility classes. | 
 
		 
		  | 3.1 Dealing with Failure (159-178) | Session 9 | 
 
		 
		  | Discusses exceptions and
			 cancellations. | 
 
		 
		  | 3.2 Guarded Methods
			 (179-198) | Session 10 | 
 
		 
		  | Introduces
			 the guard constructions used in conservative designs. | 
 
		 
		  | 3.3 Structuring and Refactoring Classes
			 (199-218) | Sessions 11 + 12 | 
 
		 
		  | Presents structural patterns for classes
			 employing concurrency control. | 
 
		 
		  | 3.4 Using Concurrency Control
			 Utilities (219-236) | Session 13 | 
 
		 
		  | Shows how utility
			 classes reduce complexity while improving reliability, performance, and
			 flexibility. | 
 
		 
		  | 3.5 Joint Actions (237-248) | Session 14 | 
 
		 
		  | Shows how to control actions that depend
			 on the states of multiple participants. | 
 
		 
		  | 3.6 Transactions
			 (249-264) | Session 15 | 
 
		 
		  | Provides a brief
			 overview of transactional concurrency control. | 
 
		 
		  | 3.7 Implementing Utilities (265-280) | Session 16 | 
 
		 
		  | Illustrates the techniques used in the
			 construction of some common utilities. | 
 
		 
		  | 4.1 Oneway Messages
			 (281-304) | Session 17 | 
 
		 
		  | Presents some basic
			 options for implementing oneway messages. | 
 
		 
		  | 4.2 Composing Oneway Messages (305-324) | Session 18 | 
 
		 
		  | Discusses the use of oneway messages in
			 component networks. | 
 
		 
		  | 4.3 Services in Threads
			 (325-342) | Session 19 | 
 
		 
		  | Presents alternatives
			 for implementing service threads. | 
 
		 
		  | 4.4 Parallel Decomposition (343-366) | Session 20 | 
 
		 
		  | Examines techniques used to improve
			 performance with multiple processors. | 
 
		 
		  | 4.5 Active Objects
			 (367-376) | Session 21 | 
 
		 
		  | Provides an overview of
			 constructs and frameworks for systems of active objects. | 
 
	 
Disclaimer: These questions can and should be augmented and / or
		replaced by questions raised by the participating study group members.
		Please bring your own questions to each study session!
 
	  
		 
		  | 1.1 Using Concurrency Constructs
			 (1-18) | Session 1 | 
 
		 
		  |  
				When would you want to create a daemon Thread?Why have suspend, resume, stop, destroy been
				  deprecated?When would it be useful to create a ThreadGroup? | 
 
		 
		  |  | 
 
		 
		  | 1.2 Objects and Concurrency
			 (19-36) |  | 
 
		 
		  |  
				What classes of problems can concurrent programs help solve
				  (hint: optimization)?What benefits do concurrent programs offer over sequential
				  programs?How can we decide whether a system needs separate machines,
				  processors, processes, or threads?What are the trade-offs (costs v. benefits) of each kind of
				  separation?What thread scheduling strategies does Java support? | 
 
		 
		  |  | 
 
		 
		  | 1.3 Design Forces (37-56) | Session 2 | 
 
		 
		  |  
				How are performance and reusability related to safety and
				  liveness? What other qualities contribute to safety and liveness?What other kinds of safety concerns are there besides type
				  safety and multithread safety (hint: consider transactions and ACID
				  properties)?Doug Lea lists several qualities that can be used to measure
				  performance. How can we measure reuse and reusability? | 
 
		 
		  |  | 
 
		 
		  | 1.4 Before/After Patterns
			 (57-68) | Session 3 | 
 
		 
		  |  
				What are the benefits and costs of the various approaches to
				  implementing before/after patterns?Is the cost of instantiating a method adapter worth the benefit
				  of factoring out the lifecycle guarantees into a single location (also see:
				  Resource Manager)? | 
 
		 
		  |  | 
 
		 
		  | 2.1 Immutability (69-74) | Session 4 | 
 
		 
		  |  
				How can the fields of an object become accessible before its
				  construction is complete?Why is it important to ensure that flyweights are completely
				  constructed before they are published? | 
 
		 
		  |  | 
 
		 
		  | 2.2 Synchronization (75-98) |  | 
 
		 
		  |  
				When would it be useful to know which of several threads owns a
				  lock?When and why is fairness important during lock
				  acquisition?What are the benefits of reentrant locking? Are there any
				  drawbacks?When would it be appropriate to use a volatile field
				  instead of synchronized methods or blocks? | 
 
		 
		  |  | 
 
		 
		  | 2.3 Confinement
			 (99-116) | Session 5 | 
 
		 
		  |  
				What are the trade-offs associated with tail-call
				  hand-offs?Given the consequences of thread-based confinement (page 106),
				  which of the available options seems most flexible?When would thread-based confinement be inappropriate?On page 112, the take protocol has often been called
				  orphan and the put protocol often called adopt (see
				  Taligent's Guide to Designing Programs). How can
				  these two protocols (however named) be combined to implement a clean and
				  confined resource transfer? (hint: use the stack, e.g.,
				  x.adoptResource(y.orphanResource())) | 
 
		 
		  |  | 
 
		 
		  | 2.4 Structuring and Refactoring Classes
			 (117-146) | Sessions 6 + 7 | 
 
		 
		  |  
				What are semantic guarantees (hint: class invariants, method
				  post-conditions)? How can they be weakened?Given the fragility of double-checked locks and the likelihood
				  that
				  they will break or be used inappropriately, would you
				  ever use them? If so, when?Does a "single giant lock" offer a significant opportunity for
				  refactoring?Should the use of open calls always be documented to clarify
				  the contractual obligations of the called methods?Is splitting a class (via refactoring) preferable to merely
				  splitting a lock within the class? When would one be preferable to the
				  other?Are explicitly immutable interfaces preferable to runtime
				  immutability (hint: catching contract violations during compilation rather than
				  execution)?How can the
				  Resource Manager pattern be adapted to enforce the correct
				  usage of resources in open containers? | 
 
		 
		  |  | 
 
		 
		  | 2.5 Using Lock Utilities
			 (147-158) | Session 8 | 
 
		 
		  |  
				How can the awkward before/after construction on page 148 be
				  simplified (hint: make acquire and release reentrant)?What kind of method adapter signature will support passed
				  parameters and returned results?Can shared resource allocations be pre-empted, or must Java
				  threads always coordinate and cooperate?Do coupled locks introduce a greater likelihood of races and
				  deadlocks between competing threads?If so, how can that be resolved (hint: coupled lock
				  managers)?What kind(s) of fairness policy(s) will ensure that read-write
				  locks prevent starvation between contending readers and writers? | 
 
		 
		  |  | 
 
		 
		  | 3.1 Dealing with Failure (159-178) | Session 9 | 
 
		 
		  |  
				When is each of the six general responses to failed actions
				  appropriate (termination, continuation, rollback, recovery, retry,
				  handlers)?When are thread interruption checks automatically performed
				  within the Java library?When are thread interruption checks not performed, i.e., when
				  are threads dormant while waiting for a resource?Why are lock utilities useful for cancellation protocols (hint:
				  reduced dormancy)?What kinds of safety concerns arise in relation to
				  Thread.stop, i.e., why was it deprecated?What (relatively) safe alternatives are there for terminating a
				  thread and diminishing its use of system resources if the thread fails to
				  terminate? | 
 
		 
		  |  | 
 
		 
		  | 3.2 Guarded Methods
			 (179-198) | Session 10 | 
 
		 
		  |  
				How do guarded methods extended synchronized methods?
				  How do guards differ from traditional conditionals?How does concurrent constraint programming help solve
				  state-based design problems?What are the commonly used alternatives for representing
				  state?How do predicate states differ from enumerated states? What are
				  their benefits?When can starvation become an issue in state-based concurrent
				  program designs?How can slipped conditions and missed signals be avoided?Why is notifyAll used more often than notify to
				  awaken waiting threads?Why is it better to avoid busy waits? What are better
				  alternatives? | 
 
		 
		  |  | 
 
		 
		  | 3.3 Structuring and Refactoring Classes
			 (199-218) | Sessions 11 + 12 | 
 
		 
		  |  
				In general, how can logical state analysis help determine the
				  optimal usage of wait and notify during state transition
				  operations?The state table on page 200 defines the states and the legal
				  transitions for a BoundedBuffer. What additional information is needed to
				  determine the optimal usage of wait and notify during the state
				  transition operations?How can conflicts between a large set of operation pairs be
				  resolved with a minimum of custom code per each pair?How can the examples for tracked states and conflict sets be
				  improved with refactoring (hint: extract methods)?When can starvation become an issue with readers and
				  writers?Why is it useful to separate functionality as non-public
				  methods from concurrency control as public methods?How can lockouts be avoided in nested monitors? | 
 
		 
		  |  | 
 
		 
		  | 3.4 Using Concurrency Control
			 Utilities (219-236) | Session 13 | 
 
		 
		  |  
				How are semaphores related to mutual exclusion locks, resource
				  pools, bounded buffers, and synchronous channels?In what kind of applications will fairness issues usually
				  arise?What is priority inversion, and how can it be countered?What are the typical applications of binary latches?What rarely useful mechanism finds an appropriate usage in
				  latching variables?When are exchangers useful (hint: double buffering)?When are condition variables useful (hint: legacy code
				  conversion)? | 
 
		 
		  |  | 
 
		 
		  | 3.5 Joint Actions (237-248) | Session 14 | 
 
		 
		  |  
				What are some of the factors to consider when designing joint
				  actions?What is the main goal of joint action designs?What are the general structure and behavior of classes involved
				  in joint actions?What are some of the conflict resolution strategies used to
				  prevent deadlocks in joint action designs?What is the best way to avoid design issues associated with
				  joint actions? | 
 
		 
		  |  | 
 
		 
		  | 3.6 Transactions
			 (249-264) | Session 15 | 
 
		 
		  |  
				What are the four steps in the basic transaction protocol?What are the two complementary sets of policies that can be
				  applied to transaction protocols?How do these two policies effect the design of transactional
				  interfaces and implementations?When would it make sense to support both optimistic and
				  conservative transaction policies?How can the detailed analysis of the structure of transaction
				  policies help determine which to choose (hint: cost comparison)?What is the relationship between a property constraint and the
				  ability (right) to veto a property change? | 
 
		 
		  |  | 
 
		 
		  | 3.7 Implementing Utilities (265-280) | Session 16 | 
 
		 
		  |  
				Given the complexity of the methods in Semaphore, how would you
				  refactor them with Extract Method?What are the potential performance costs of using
				  notifyAll versus notify?Given that single-threaded notification designs usually
				  increase design complexity, will it usually be worth the performance gain to
				  pursue such designs?Why might collapsing the classes within a design that splits
				  state-dependent actions make them more efficient?Given the increased complexity from collapsing classes, when
				  (if ever) would this approach be warranted?Is there an appropriate utility class that could be used in
				  place of WaitQueue for the FIFO semaphore?In comparison with the suggested FIFO semaphore implementation,
				  how could a priority semaphore be implemented?How could a task-oriented semaphore for resolving conflict sets
				  be designed?How could the queuing policy for the various kinds of
				  queue-based semaphores be factored out? | 
 
		 
		  |  | 
 
		 
		  | 4.1 Oneway Messages
			 (281-304) | Session 17 | 
 
		 
		  |  
				What data characteristics distinguish the various kinds of
				  message formats described in section 4.1.1 (hint: binary v. text, instance v.
				  class, event v. 1-way request)?In an open call design, what will happen if the request arrival
				  rate exceeds the request acceptance rate (which is determined by the local
				  state update latency)?What are some of the reasons one might use a thread-per-message
				  design? What kind of limitations will usually be encountered with
				  thread-per-message designs?What trade-offs do thread pools introduce? How can thread pool
				  saturation be addressed? How do web servers and app servers typically address
				  saturation?Given that a Swing event queue is single-threaded, can it be
				  easily saturated? What are the observable consequences of such saturation? How
				  can such saturation be eliminated?How does the JDK Timer framework in java.util compare with that
				  suggested in section 4.1.4.3? How might a Schedule be represented indepently of
				  tasks, threads, Timers, and the system clock?When using a busy-wait loop to manage event-driven tasks, would
				  it be beneficial to use the number of tasks (or the average per some time
				  period) to control the sleep / wait duration?When commands do not arrive as units, a worker thead can stall.
				  Is there an alternative to using a buffering scheme to prevent stalling (hint:
				  test for available() >= N, where N is a fixed command length)? | 
 
		 
		  |  | 
 
		 
		  | 4.2 Composing Oneway Messages (305-324) | Session 18 | 
 
		 
		  |  
				What are some of the goals satisfied by flow network designs
				  (hint: see the end of section 4.2.1.2)?What are some examples of systems from your development
				  practice that either did benefit or would benefit from the use of a flow
				  network design?What were the idioms, patterns, and metaphors relevant to your
				  designs?How do they compare with those described in this section? | 
 
		 
		  |  | 
 
		 
		  | 4.3 Services in Threads
			 (325-342) | Session 19 | 
 
		 
		  |  
				How have you (or would you) use Thread.join and futures
				  in your own concurrent program designs?If the Callable interface in section 4.3.3.1 is awkward,
				  how would you improve upon it or generate a design based on this idea?How does the "elevator algorithm" from section 4.3.4 work? Is
				  there any situation from your own coding practice where you (could) have
				  applied this? | 
 
		 
		  |  | 
 
		 
		  | 4.4 Parallel Decomposition (343-366) | Session 20 | 
 
		 
		  |  
				What are the primary goals we're trying to satisfy with task
				  granularity and structure in fork/join decomposition solutions?How do the forces represented by these goals trade off against
				  each other?What design techniques can be applied to balancing these
				  forces, i.e., what frameworks and design steps can be used?How can the number of forked subtasks be varied
				  dynamically?When are callback-based fork/join designs typically used?When and how can trees improve the efficiency of fork/join
				  designs?Is there any situation from your own coding practice where you
				  (could) have used a cyclic barrier?  | 
 
		 
		  |  | 
 
		 
		  | 4.5 Active Objects
			 (367-376) | Session 21 | 
 
		 
		  |  
				What differentiates active objects from other kinds of
				  objects?Is there any situation from your own coding practice where you
				  (could) have used active objects?How do CSP processes and channels behave?What benefits can be gained from using CSP in designs?Is there any situation from your own coding practice where you
				  (could) have used CSP? | 
 
		 
		  |  | 
 
	 
 
	 Java is a trademark of Sun Microsystems, Inc.