From: John B. Matthews on 10 Mar 2010 18:07 In article <S9Sln.90254$Ye4.78776(a)newsfe11.iad>, Knute Johnson <nospam(a)rabbitbrush.frazmtn.com> wrote: > On 3/10/2010 10:34 AM, markspace wrote: > > Knute Johnson wrote: > >> Does anybody know if the Observable/Observer calls to update() are on > >> the EDT? > > > Considering that Observer is just an interface and it would depend > > on the implementation, and that no Java Swing classes that I know > > of actually implement Observer, I'd have to guess the answer is in > > general "no." > > The Observable class method, notifyObservers() is called and that > then calls all Observer.update() methods. I'm curious to know if the > Observable puts those calls onto the EDT. As markspace has elaborated, the answer is no. Not long ago, I proposed that on Observable can invoke notifyObservers() on the EDT, as via javax.swing.Timer, but access to any data shared between threads must still be correctly synchronized. I found this discussion very helpful <http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/4c4a6b46ffd2d31f> and I have tried to express my understanding in this example: <http://sites.google.com/site/drjohnbmatthews/threadwatch> -- John B. Matthews trashgod at gmail dot com <http://sites.google.com/site/drjohnbmatthews>
From: Knute Johnson on 10 Mar 2010 19:38 On 3/10/2010 3:07 PM, John B. Matthews wrote: > In article<S9Sln.90254$Ye4.78776(a)newsfe11.iad>, > Knute Johnson<nospam(a)rabbitbrush.frazmtn.com> wrote: > >> On 3/10/2010 10:34 AM, markspace wrote: >>> Knute Johnson wrote: >>>> Does anybody know if the Observable/Observer calls to update() are on >>>> the EDT? >> >>> Considering that Observer is just an interface and it would depend >>> on the implementation, and that no Java Swing classes that I know >>> of actually implement Observer, I'd have to guess the answer is in >>> general "no." >> >> The Observable class method, notifyObservers() is called and that >> then calls all Observer.update() methods. I'm curious to know if the >> Observable puts those calls onto the EDT. > > As markspace has elaborated, the answer is no. Not long ago, I proposed > that on Observable can invoke notifyObservers() on the EDT, as via > javax.swing.Timer, but access to any data shared between threads must > still be correctly synchronized. I found this discussion very helpful > > <http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/4c4a6b46ffd2d31f> > > and I have tried to express my understanding in this example: > > <http://sites.google.com/site/drjohnbmatthews/threadwatch> > I looked through the source code and all of the methods of Observable are synchronized on the Observable instance. So threads that read any argument that is passed in and stored needs to be synchronized as well. I'm not sure how to do that. The whole point of using Observer/Observable is to disconnect the two classes. Calling notifyObservers() from a known thread could be used to synchronize via thread containment but the docs imply that the calling thread isn't necessarily guaranteed to be the writing thread in the future. In the application that I am writing, I am passing an Integer). In the Observer.update() method I store that Integer. I'm storing it in a volatile int so that solves the visibility problems for the reading thread but what if you had a mutable Object to pass? Thanks, -- Knute Johnson email s/nospam/knute2010/
From: John B. Matthews on 10 Mar 2010 23:39 In article <WXWln.10092$QL4.95(a)newsfe24.iad>, Knute Johnson <nospam(a)rabbitbrush.frazmtn.com> wrote: > On 3/10/2010 3:07 PM, John B. Matthews wrote: > > In article<S9Sln.90254$Ye4.78776(a)newsfe11.iad>, > > Knute Johnson<nospam(a)rabbitbrush.frazmtn.com> wrote: > > > >> On 3/10/2010 10:34 AM, markspace wrote: > >>> Knute Johnson wrote: > >>>> Does anybody know if the Observable/Observer calls to update() are on > >>>> the EDT? > >> > >>> Considering that Observer is just an interface and it would > >>> depend on the implementation, and that no Java Swing classes that > >>> I know of actually implement Observer, I'd have to guess the > >>> answer is in general "no." > >> > >> The Observable class method, notifyObservers() is called and that > >> then calls all Observer.update() methods. I'm curious to know if > >> the Observable puts those calls onto the EDT. > > > > As markspace has elaborated, the answer is no. Not long ago, I > > proposed that on Observable can invoke notifyObservers() on the > > EDT, as via javax.swing.Timer, but access to any data shared > > between threads must still be correctly synchronized. I found this > > discussion very helpful > > > > <http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/4c4a6b46ffd2d31f> > > > > and I have tried to express my understanding in this example: > > > > <http://sites.google.com/site/drjohnbmatthews/threadwatch> > > I looked through the source code and all of the methods of Observable > are synchronized on the Observable instance. So threads that read > any argument that is passed in and stored needs to be synchronized as > well. I'm not sure how to do that. The whole point of using > Observer/Observable is to disconnect the two classes. Interesting. The synchronized block in notifyObservers() mentions two, worst-case potential races: 1) a newly-added Observer will miss a notification in progress, and 2) a recently unregistered Observer will be wrongly notified when it doesn't care. Unfortunately, the API doesn't mention being synchronized. > Calling notifyObservers() from a known thread could be used to > synchronize via thread containment but the docs imply that the > calling thread isn't necessarily guaranteed to be the writing thread > in the future. I read the Observable API as "but subclasses [of Observable] may ... deliver notifications on separate threads." > In the application that I am writing, I am passing an Integer). In > the Observer.update() method I store that Integer. I'm storing it in > a volatile int so that solves the visibility problems for the reading > thread but what if you had a mutable Object to pass? I'm not sure about that. -- John B. Matthews trashgod at gmail dot com <http://sites.google.com/site/drjohnbmatthews>
From: Peter Duniho on 10 Mar 2010 23:48 Knute Johnson wrote: > I looked through the source code and all of the methods of Observable > are synchronized on the Observable instance. The class has been around since 1.0. I suspect the synchronization was simply part of a misguided attempt to provide generally thread-safe classes, a la Vector. > So threads that read any > argument that is passed in and stored needs to be synchronized as well. > I'm not sure how to do that. The whole point of using > Observer/Observable is to disconnect the two classes. As the docs make clear, the Observable class is specifically _not_ about threading. It's every bit as useful in a single-threaded program, but of course if you choose to call notifyObservers() in a thread other than the one where handling of data in the update() method should be done (e.g. EDT issues), or the update() method will be touching data that needs to be synchronized between other threads, that would be up to your Observer implementation to handle. That said… > Calling notifyObservers() from a known thread could be used to > synchronize via thread containment but the docs imply that the calling > thread isn't necessarily guaranteed to be the writing thread in the future. What the docs seem to imply to me is that while the default implementation of Observable simply calls the update() method for all the Observers, that sub-classes may have arbitrarily different behavior. Of course, this is a strong hint that if you would like your update() methods to be invoked on the EDT, that one obvious approach would be to write an Observable sub-class that does in fact do that. > In the application that I am writing, I am passing an Integer). Passing an Integer to what? The notifyObservers() method? Something else? I note that in many situations, one might find that it makes sense for a data container object to inherit Observable directly, such that no other data reference need be passed to the notifyObservers() method (and the update() method would get "null" for the "arg" parameter). Note the language in the documentation, in which it describes the "change" as happening to the Observable itself, as opposed to some other object. Of course, you can provide an object in the notifyObservers() call, but then that means your own code needs to keep track of which Observable goes with which mutable state/data. A reasonable alternative IMHO would be for your Observable itself to be what's changed. (In fact, I'm a little surprised that there's not an equivalent interface to go with Observable; it makes sense for a default implementation to be provided, but what about other types that might also want to be "observable" but which for other reasons can't inherit Observable? They're going to wind up with some kind of de facto "observable" interface anyway…might as well publish one in the JDK :) ). > In the > Observer.update() method I store that Integer. I'm storing it in a > volatile int so that solves the visibility problems for the reading > thread but what if you had a mutable Object to pass? If the mutable Object was thread-safe, then it would handle that. Otherwise, you'd have to use some mechanism for ensuring synchronization. As far as I know, Java doesn't have an explicit memory barrier API, so "synchronized" is probably the best approach for simple mutation observability issues. Pete
From: Knute Johnson on 11 Mar 2010 00:45
On 3/10/2010 8:48 PM, Peter Duniho wrote: > If the mutable Object was thread-safe, then it would handle that. > Otherwise, you'd have to use some mechanism for ensuring > synchronization. As far as I know, Java doesn't have an explicit memory > barrier API, so "synchronized" is probably the best approach for simple > mutation observability issues. > > Pete And there's the rub. If you have as in my case, two separate classes, where you don't want to share data other than that which is shared via the Observable/Observer, how do you get the Observable instance in the Observer to then use to synchronize with? You have to assume that a different thread could read the data after it was stored via the Observer.update() method. -- Knute Johnson email s/nospam/knute2010/ |