From: Knute Johnson on
On 3/10/2010 8:39 PM, John B. Matthews wrote:
> 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.
>

I'm thinking now that maybe I didn't design this quite correctly.

--

Knute Johnson
email s/nospam/knute2010/

From: markspace on
Knute Johnson wrote:
> 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.
>


What are you trying to do? Are you trying to pass data between threads,
or are you actually trying to implement an Observer Pattern?

If you're implementing an Observer, you should probably take care to
synchronize yourself, since the Observer really doesn't guarantee
synchronization.

If you're just looking for a memory barrier API, I think several classes
in java.util.concurrent guarantee synchronization explicitly. This
includes lock objects, executors, concurrent collections and probably a
few others. This might be as simple as dumping the data into a
BlockingQueue, and then reading it with a different thread.



From: Peter Duniho on
Knute Johnson wrote:
> 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.

Without a code example, it's hard for me to know for sure what you're
talking about. However, if you are asking how to get the reference to
the Observable instance so that you can use that reference in a
"synchronized" statement, then the answer is "you don't, nor should you".

Unless you specifically want to write some special thread-safe
Observable sub-class that handles this, the synchronization isn't
something the Observable needs to know about at all, nor would it be
anything that needs the Observable instance itself. The synchronization
is between the threads modifying the data and reading the data, while
the Observable is just a by-stander.

If you can provide a SSCCE that illustrates the relationship between
your Observable, an Observer, and whatever other code exits that is
modifying a mutable class instance, as well as examining that mutable
class instance in a different thread, then surely a solution can be
described that provides the necessary synchronization, but without
necessarily making the Observable a central figure in that.

Note that, depending on how strict you want to be about this whole
"don't want to share data other than that which is shared via the
Observable/Observer", you may require a wrapper class to impose the
synchronization needed.

But with an Observable that is not itself imposing a multi-threaded
implementation, it's not at all clear how you managed to get two classes
that know nothing of each other except for the Observable, and yet which
are going to access the same data on two different threads. Either each
class is associated with its own thread, and one knows about the other,
or only one class includes code executing on two different threads (e.g.
an Observer in one thread, and some other stuff in another), in which
case it only needs to synchronize within itself.

Basically, until it's clear how it is you've got an Observable that
involves itself in cross-thread communication, in which two different
threads involve two completely mutually-isolated classes except for an
Observable mediating, and yet in which the Observable itself isn't
involved in the threading, it's very hard to suggest a design that will
work for you.

After all, since the default Observable implementation simply calls
update() in the same thread where notifyObservers() was called, how is
it that the writer thread is different from the reader thread in the
first place?

I suspect that once you've focused on the answer to that question,
you'll see the division between the two threads where the
synchronization has to take place, and it probably will be simple to
implement that synchronization independently of the Observable behavior.

If you post a SSCCE, I'm sure you'll get good advice, if not from me
then from someone else. :)

Pete
From: Knute Johnson on
On 3/10/2010 10:01 PM, markspace wrote:
> Knute Johnson wrote:
>> 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.
>>
>
>
> What are you trying to do? Are you trying to pass data between threads,
> or are you actually trying to implement an Observer Pattern?
>
> If you're implementing an Observer, you should probably take care to
> synchronize yourself, since the Observer really doesn't guarantee
> synchronization.
>
> If you're just looking for a memory barrier API, I think several classes
> in java.util.concurrent guarantee synchronization explicitly. This
> includes lock objects, executors, concurrent collections and probably a
> few others. This might be as simple as dumping the data into a
> BlockingQueue, and then reading it with a different thread.

It would seem that there should be some method simpler than having to
create a BlockingQueue to hand data between the Observable and the Observer.

I have two classes that happen to be extensions of JPanels. Both of
them have methods to input data that is then displayed (in various
forms) on the other. The Observable/Observer appeared to be perfectly
suited for this purpose. Then I got to thinking about which thread was
being used and the fact that different threads could be writing/reading
the data. That caused me to try to figure out how to synchronize that
data between the classes. In my actual app, I write the data to a
volatile int and that I'm sure will work but what if I needed to pass a
reference to mutable object and wanted to ensure that the Observer had
the latest information.

So I'm sure the BlockingQueue would work but doesn't there have to be a
simpler way? Or have I just designed this in a way that it was never
intended to be?

Thanks,

--

Knute Johnson
email s/nospam/knute2010/

From: Peter Duniho on
markspace wrote:
> Knute Johnson wrote:
>> On 3/10/2010 8:48 PM, Peter Duniho wrote:
>>> [...] 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.
>>
>> 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.
>
> [...]
> If you're just looking for a memory barrier API, I think several classes
> in java.util.concurrent guarantee synchronization explicitly. [...]

Note, as a minor point of clarification, that by "memory barrier", I
mean specifically something that introduces a memory barrier for reads
and writes, solely for the sake of the barrier rather than as part of
some other synchronization construct (e.g. latch, atomic classes, etc.).

Any synchronization object will implicitly include a memory barrier, but
one can write lock-free code that still has a memory barrier to ensure
coherency of data between threads.

Though, frankly, it's hard to write lock-free code correctly (it's
certainly not something I go around trying to do myself), and the
"volatile" keyword can usually provide as much of a memory barrier as is
needed.

That is, you can ensure data is fully updated and visible by using a
volatile variable as a gate-keeper…everything written before the
volatile variable is written will be seen by any thread that reads that
data after reading the volatile variable, as long as it reads the
volatile variable after it was written.

In other words, if the reading thread sees the change to the volatile
variable, it will necessarily also see all changes to any data that
happened before the volatile variable was written.

Pete
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7
Prev: Exception Handling
Next: First class developer: who ?