⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statebased.html

📁 Concurrent Programming in Java
💻 HTML
字号:
<html><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><html> <head><title>State-Based Notifications</title></head><BODY bgcolor=#ffffee vlink=#0000aa link=#cc0000><body><h1>State-Based Notifications</h1>As a default, conservative strategy for dealing with synchronization,you might place <code>notifyAll</code> calls every time you change thevalue of any instance variable that's mentioned in any<code>wait</code> condition.  But you can almost always do better thanthis (in terms of efficiency, understandability, and design elegance)by associating synchronization mechanics with the high-level<em>logical</em> state of an object.<p> The idea is that instead of dealing with particular values andvariables, <code>waits</code> should deal with logical stateconditions. And similarly, when any operation causes a logical state<em>change</em>, a notification is issued. The technique is applicablewhenever you can partition the different behaviors of an object interms of a finite (usually small) number of logical states.<p> For example, in the <ahref="synchDesign.html#secCounter" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/synchDesign.html#secCounter">BoundedCounter</a> class, we canidentify three logical states, along with the behavior of<CODE>inc</CODE> and <CODE>dec</CODE> associated with these states:<PRE>state     condition                inc           dec-------------------------------------------------------bottom    count == minVal          go            waitmiddle    minVal < count < maxVal  go            gotop       count == maxVal          wait          go</PRE><p>There are two ways to go from here, using either <em>explicit</em>or <em>implicit</em> state tracking.<h2>Explicit State Tracking</h2>Logical state can be encoded in an instance variable, and maintainedby a method that issues notifications only upon state<EM>changes</EM>.  The <CODE>wait</CODE> methods should then bechanged to wait for appropriate values of the state variable. Forexample:<PRE>class BoundedCounterVS implements BoundedCounter {  static final int bottomState = 0;  static final int middleState = 1;  static final int topState    = 2;  public synchronized int value() { return count_; }  public synchronized void inc()  { waitUntilIncrementable();                                    ++count_;                                     checkState();  }  public synchronized void dec()  { waitUntilDecrementable();                                    --count_;                                     checkState();  }   public BoundedCounterVS()       { count_ = minValue; myState_ = bottomState; }  private int count_;  private int myState_;  private synchronized void waitUntilIncrementable() {    while (myState_ == topState)     try { wait(); } catch(InterruptedException ex) {};  }  private synchronized void waitUntilDecrementable() {    while (myState_ == bottomState)     try { wait(); } catch(InterruptedException ex) {};  }  private synchronized void checkState() {    int oldState = myState_;    if      (count_ == minVal) myState_ = bottomState;    else if (count_ == maxVal) myState_ = topState;    else                       myState_ = middleState;    if (myState_ != oldState) notifyAll();  }}</PRE>This code will generate far fewer notifications than the originalversion in which <em>every</em> change to <code>count_</code> caused anotification. Since <code>notifyAll</code> is a relatively expensiveoperation in Java, this version will probably run faster.<h2>Implicit Tracking</h2>With implicit tracking, representations of logical state are encodeddirectly into the methods performing the waiting and notification.<p>For example, in <CODE>BoundedCounter</CODE>, the only changes thatcould possibly affect waiting threads are those that step<CODE>count_</CODE> away from <CODE>minVal</CODE> and<CODE>maxVal</CODE>.  Thus, the <CODE>inc()</CODE> method need onlynotify if, before the increment, the <CODE>count_ == minVal</CODE>,and conversely for <CODE>dec()</CODE>, as in:<PRE>  public synchronized void inc()  { waitUntilIncrementable();                                    ++count_;                                     if (count_ -1 == minVal) notifyAll();  }  public synchronized void dec()  { waitUntilDecrementable();                                    --count_;                                     if (count_ + 1 == maxVal) notifyAll();  } }</PRE><h3>Comparison</h3><p> Explicit state tracking is almost always preferable to implicittracking. While it can sometimes be made to generate fewernotifications, implicit tracking pays a much greater penalty offragility and inflexibility.<p> For example, here, the implicit version does not bother generating<code>notifyAll</code> when it steps up <em>to</em> the <code>count_== maxVal</code> state since there turns out not to be any actionassociated with that transition. The explicit version does thenotification anyway, blind to the fact that there don't happento be any ``consumers'' of this logical state change.<p> However, it would be impossible to build subclasses of theimplicit version that include methods with guards waiting for anyother property of <CODE>count_</CODE> than the particular ones sensedin the <code>inc()</code> and <code>dec()</code> methods withoutcompletely rewriting the methods. (Granted, this would not be a bigdeal here, but would be if we were not using toy examples forillustration!). This is another example of the ``inheritanceanomaly''.<p> In contrast the explicit version contains a good deal moreflexibility.  Subclasses can subdivide the logical states; forexample, they could add explicit state <code>nextToBottomState</code>if there were something special that needed to be done when the countis exactly one. Similarly, because all of the notification code isencapsulated within <code>checkState</code>, subclasses can overrideit to refine it in ways that are more specialized yet still consistentwith the code that relies upon it.<h2>State Objects</h2>One can go further down along the explicit state tracking route byusing the ``States as Objects'' pattern (See the <AHREF="javascript:if(confirm('http://st-www.cs.uiuc.edu/users/patterns/Books.html  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://st-www.cs.uiuc.edu/users/patterns/Books.html'" tppabs="http://st-www.cs.uiuc.edu/users/patterns/Books.html"> DesignPatterns</A> book or <ahref="javascript:if(confirm('http://g.oswego.edu/dl/oosdw3/ch19/ch19.html  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl/oosdw3/ch19/ch19.html'" tppabs="http://g.oswego.edu/dl/oosdw3/ch19/ch19.html"> OOSD</a>.)  Here,rather than encoding the state as a variable, you encode it as areference to an object that behaves <em>only</em> as the main objectwould if it were in the associated state. This strategy is useful (andworth its set-up overhead in terms of associated helper classes) whennot only the wait conditions, but also the other action code variesacross states. This is not the case for the BoundedCounter examplebut (<em>to be continued</em>).<p>For some further variants and extensions to this pattern, see papersby <a href="javascript:if(confirm('http://choices.cs.uiuc.edu/sane/home.html  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://choices.cs.uiuc.edu/sane/home.html'" tppabs="http://choices.cs.uiuc.edu/sane/home.html"> AamodSane</a>).<p><a href="aopintro.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/aopintro.html">[Concurrent Programming in Java]</a><hr><address><A HREF="javascript:if(confirm('http://g.oswego.edu/dl  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl'" tppabs="http://g.oswego.edu/dl">Doug Lea</A></address><!-- hhmts start -->Last modified: Tue Feb 20 06:29:00 EST 1996<!-- hhmts end --></body> </html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -