Thread synchronization

T

Thomas G. Marshall

xarax coughed up:
"Thomas G. Marshall"


It is incorrect to think of synchronization as
protecting "code". It protects data. If there
were no code, there would be no processing and
no need for computers. Code is a "given".

You are protected from concurrent execution of that code. Code itself is
always there, sure. Precisely /what/ code that is protected by mutex is the
issue.

public class Fubar
{
protected int gonk;

public synchronized void snafu()
{
gonk++;
}

public synchronized void gorko()
{
gonk--;
}
}

Will the "synchronized" keyword prevent multiple
threads from concurrently executing the code? Say,
thread#1 calls snafu() and thread#2 calls gorko().

The answer is, "it depends". Maybe yes, maybe
no. Why? Because snafu() and gorko() are instance
methods, and the synchronization depends on which
instance each thread is referring to at the time
the method is called. it's all about the data, not
about the code.

It's all about who is holding the lock. And determining whether or not your
synchronized block is actually working or not depends upon what you have
placed within it.

Again, the term "protecting" is causing a terminology collision of sorts.
When I say that the code is being protected, what I'm saying (and have said
over and over) is that multiple executions of the code are prevented from
running concurrently (when done right).

For example, if you thought that I was saying that the code itself was
mutable and itself needed protection from alteration as such, then you'd be
right in correcting me.

But to understand what is happening, you need to be aware that all
synchronization and hence protection of the data, depends entirely on what
is placed within the synchronization blocks. It is all about the code: it
is all about what code is protected from concurrent execution.

Another way to describe it is synchronization
governs access to a resource. Data in memory can
be a resource. Files on a harddrive can be a
resource. There are synchronization mechanisms
to ensure the consistency of data and proper
access to resources. Any such synch mechanism
is a "protocol" that must be observed by all
threads that access the *same* resource. With
proper design and implementation, the resource
is protected from corruption.

Sure and how is this accomplished? By carefully governing exactly /what/
code is placed under mutex protection.
mutex protects data, not code.

Again, terminology collision (of sorts). I think we've collided enough for
one week.
 
B

Bent C Dalager

Again, the term "protecting" is causing a terminology collision of sorts.
When I say that the code is being protected, what I'm saying (and have said
over and over) is that multiple executions of the code are prevented from
running concurrently (when done right).

That isn't technically correct. Multiple executions of the code _can_
all run at the same time, if the object holding the lock is different
in the different threads. Given a synchronized(this) block, it is
evident that you are only guaranteed that the block isn't running
simultaneously in multiple threads _for any one given instance of the
class_. If you have an arbitrarily large number of instances, then the
"protected" code block could be running simultaneously in an
arbitrarily large number of threads - but with different data sets.

This basically comes down to code being shared between different
instances of the same class while the mutex may not be.

It seems from this that to simply say that "the code is protected" is
at least an incomplete view of the situation. That would only seem an
appropriate assessment in the event of a synchronized(getClass())
block (or similar) although, of course, that will break down in the
presence of the creative use of class loaders.
But to understand what is happening, you need to be aware that all
synchronization and hence protection of the data, depends entirely on what
is placed within the synchronization blocks. It is all about the code: it
is all about what code is protected from concurrent execution.

It is also, of course, very much about which mutex you are using and
the mutex generally represents the data you are trying to protect. It
seems to me to be a matter of personal preference whether to consider
that the data (given by the mutex) is what is being protected, or if
it is the code (given by the extent of the code block) that is being
protected. At any rate, to consider only one of these two views to be
correct and the other to be wrong seems to me to lead to an incomplete
and possibly erroneous view of what synchronization is and how it is
to be used.

I prefer to look at synchronization as something that "restricts
concurrent access to code in order to protect data or resources".

Cheers
Bent D
 
B

Bent C Dalager

I've discovered that part of what confuses students is that in order to
externally synchronize on an object, that object needs to be 1. internally
synchronizing on /this/ (or on the class, or something else /known/, etc.),
and 2. well documented that it is doing so.

Wouldn't it be better if the class encapsulated the logic needed for
synchronizing itself and then offered this as a general service in its
interface? E.g.,

public Class SuperSyncedThing
{
private int _value;
public int getValue() { return _value; }
public void setValue(int value) { _value = value; }
public void syncedUpdate(Runnable operation)
{
synchronized(this)
{
operation.run();
}
}
}

Now the outside world doesn't need to care what mutex is to be used to
synchronize updates, you'd simply write something along the lines of

final SuperSyncedThing myThing = ...;
myThing.syncedUpdate(new Runnable())
{
public void run()
{
myThing.setValue(myThing.getValue() + 1);
}
});

By not exposing your mutex to the outside world you are making the use
of your class less low-level and dirty (in my view) and you leave
yourself free to change what mutex to use in the future without
breaking code that was written to use an older version of your class.

Of course, you could get the latter benefit by simply adding a
public Object getMutex();
to the interface, but in my universe that would still leave things
low-level and dirty :)

(Note that getValue() and setValue() don't have any internal
synchronization because changing or reading an int is an atomic
operation and so no inconsistencies can occur anyway in this case. At
least, that's the theory ... :)

Cheers
Bent D
 
L

Lee Fesperman

Thomas said:
Lee Fesperman coughed up:

It was a direct quote, without snipping.

Yes, you 'quoted' my original words without change. However, your reply consisted of
taking my sentences and switching the nouns to render them meaningless. You did it a
number of times, reminding me of a child's game.

Quoted, but no response?
The execution of such lines of code. Yep.

The effect is to say that lines of code textually 'exterior' to the synchronized block
are not protected. That is wrong. Code /within/ the block may call methods outside the
block even in different classes, packages and standard API. This code (during the call)
will be synchronized on the synchronization object's monitor.
 
C

Chris Uppal

Mike said:
You've snipped the context. I was replying to your point that you prefer

synchronized(this) {}

to

private Object lock = new Object();
synchronized(lock) {}

and explaining the dangers of the former.

This idea isn't peculiar to me, by the way. Bloch makes the same point in
_Effective Java_.

I'm still not sure I'm following you. Is your objection that without a
"hidden" lock object, it is possible for an arbitrary bit of foreign code to
execute a synchronised block on the object in question, thus potentially
preventing it from making further progress in its real task ?

If so then I think the reasoning is backwards, maybe even circular. It seems
to me that the only reason "someone else" is likely to lock "your" object
inappropriately is that the practice of taking out locks on other-than-self is
being followed. What I call spaghetti synchronisation (I admit the term is
loaded).

If you consider that in the normal case (and overwhelming majority at that), an
object will hold a lock only on itself, then the "danger" is obviously
chimerical. But, in order to avoid it, you (if I'm interpreting you correctly)
throwing away the obvious benefits to comprehension of allowing the objects to
carry the conceptual load.

That's how I see it anyway.

(I haven't read "Effective Java"; I remember looking at it in a bookshop and
thinking "nah", but I can't now remember whether that's because I thought it
misguided -- as in this case -- or just that it was telling me stuff I already
knew. I shall have to check it out again.)

-- chris
 
C

Chris Uppal

Thomas said:
This post is huge. I'm going to try to respond to as few of the salient
points as I can that I believe we are at odds with. If I snipped
something too important to miss, then I apologize, and please let me know.

[Sorry about the delayed response, to this and to other posters in this thread.
To be honest, I'd run out of appetite for the subject, and wanted to let it lie
for a few days]

Mutexes, semaphores, and all notions of synchronization and concurrency
control that I can think of exist in computer science with or without
object orientation.

Do you agree?

I do, but maybe there's one of our points of difference. I'm working in a
totally OO context -- I'm not even slightly interested in the fact that some of
the concepts I work with can be dislodged from their entanglement with Java's
vision of OO. I don't /want/ to disentangle them -- working with the "grain"
of Java and allowing OO to manage the conceptual difficulties of
synchronisation
is to me /obviously/ the best way to work.

Now I can quite see that if you are attempting teach /programming/ (as opposed
to /Java/ or at least OO programming), and the use of Java is just an expedient
choice, then I can see why you would want to keep the concepts as clearly
separated as possible. But I submit that by doing so, you risk /not/ teaching
your students the best way to use the tools in hand.

That would be a mistake.

Mistaken or not, you have not as yet persuaded me that I would be well advised
hire someone who has been trained the way that /it seems to me/ you are
advocating.

Not exactly. The code /execution/ is duplicated "in" each thread. When I
say that I am protecting lines of code from simultaneous execution

Well no. I /doesn't/ prevent simultaneous execution, nothing like it -- as you
well know, the same synchronised method, say, can be executed on two different
instance simultaneously. And it's precisely that feature of Java's approach to
concurrency that I think you are failing to emphasise. With the result that
you then have to force an unnatural expression of synchronisation in order to
compensate for the confusion you have caused by emphasising the code rather
than the objects.

And what of non-object oriented languages?

As I've said, they are neither interesting nor relevant to me (for the purposes
of this discussion -- of course!). Your position may be different. I'm
interested in the best, most natural, and easiest to make "right", way to
program /in Java/. I'm not interested in the commonality of the concepts of
computer science, because if I were using a different language, then the grain
of that language would be different and I'd approach the subject in a different
way. Of course, I'm able to take that view because, in part, I've had a good
education that /does/ include the language-independent abstractions -- I'm not
knocking the idea of teaching them. But you have to decide which you /are/
teaching: good practical OO/Java programming, or computer science.

-- chris
 
C

Chris Uppal

Thomas said:
I was going to let this go, but I just cannot.

I think I've now said all I have to say on this subject, but I did want to add
to:
Particularly when the user grabs a thread safe list using
Collections.synchronizedList().

Ugh, yes!

I'm inclined to think that that wrapper should be deprecated. It doesn't
protect the semantics of the data /in/ the collection, only of the data
structures used internally /by/ the collection. And since protecting the
meaning (which can only be done from outside) will naturally protect the
implementation too, there seems to be little need for the wrapper. It is just
an error waiting to happen...

-- chris
 
M

Mike Schilling

Chris Uppal said:
I'm still not sure I'm following you. Is your objection that without a
"hidden" lock object, it is possible for an arbitrary bit of foreign code
to
execute a synchronised block on the object in question, thus potentially
preventing it from making further progress in its real task ?

No, it's that any class C can do a

synchronized(o)

on any object o it has access to. If that object is also synchronizing on
itself, this can play havoc with its internal synchronization logic. Note
that this is independent of how well the internal synchronization is
encapsulated, or of whether the object's class is visible to C.

If so then I think the reasoning is backwards, maybe even circular. It
seems
to me that the only reason "someone else" is likely to lock "your" object
inappropriately is that the practice of taking out locks on
other-than-self is
being followed. What I call spaghetti synchronisation (I admit the term
is
loaded).

Agreed that this can be a bad practice. So can calling random methods in
other classes that aren't specifically esigned to be called by outsiders.
However, rather than depend upon convention and good manners to avoid this,
Java defines access modifiers for methods to prevent it.
If you consider that in the normal case (and overwhelming majority at
that), an
object will hold a lock only on itself, then the "danger" is obviously
chimerical. But, in order to avoid it, you (if I'm interpreting you
correctly)
throwing away the obvious benefits to comprehension of allowing the
objects to
carry the conceptual load.

I don't think

private Object lock_object();

synchronized(lock_object)

differs in concept from

synchronized(this)

particularly when you understand the reason for it.
That's how I see it anyway.

(I haven't read "Effective Java"; I remember looking at it in a bookshop
and
thinking "nah", but I can't now remember whether that's because I thought
it
misguided -- as in this case -- or just that it was telling me stuff I
already
knew. I shall have to check it out again.)

I recommend it. My experience was that some of it was well-known and
obvious, while other parts were new and valuable.
 
B

Babu Kalakrishnan

Chris said:
Mike Schilling wrote:

I'm still not sure I'm following you. Is your objection that without a
"hidden" lock object, it is possible for an arbitrary bit of foreign code to
execute a synchronised block on the object in question, thus potentially
preventing it from making further progress in its real task ?

If so then I think the reasoning is backwards, maybe even circular. It seems
to me that the only reason "someone else" is likely to lock "your" object
inappropriately is that the practice of taking out locks on other-than-self is
being followed. What I call spaghetti synchronisation (I admit the term is
loaded).

If you consider that in the normal case (and overwhelming majority at that), an
object will hold a lock only on itself, then the "danger" is obviously
chimerical. But, in order to avoid it, you (if I'm interpreting you correctly)
throwing away the obvious benefits to comprehension of allowing the objects to
carry the conceptual load.

You're oversimplifying the case - Chris. What you're saying is perfectly fine as
long as the object in question is a simple one you've created - possibly
descending from java.lang.Object. However, in a real life scenario, you very
often extend existing library classes, and you don't know (and shouldn't really
depend on) the implementation specifics. Unfortunately, the synchronization
behaviour of a class is almost always never specified in the API, and you end up
not knowing if some of the methods implemented in the superclass synchronize on
itself or not - with the result that one is never very sure if you can get into
a deadlock situation if you synchronize on "this".

If you recollect, there was a thread about a week ago when a poster was
surprised that he was getting unexpected notifications when he was "wait()"ing
on a Thread object. The fact is that the Thread object is probably sending out
notifies (which obviously means it has synchronized blocks on itself), but it is
never specified anywhere. In such a scenario, would you say that
synchronized(this) is safe to do in the case of an object descending from
java.lang.Thread ?

I recall a situation where some GUI classes that people from my organization
wrote suddenly started deadlocking when a new version of JDK was released (IIRC
it was a switch from JDK 1.1.4 to JDK 1.1.5) - We were really surprised because
our code didn't have any synchronized blocks at all (or so we thought).
Eventually the problem was traced to some code introduced by Visual Cafe (which
we used in those days for building the GUI) - where it would override the show()
method of a java.awt.Dialog to do some vague thing (I think setting the dialog
position to the centre of the screen or something), and the method was declared
"public synchronized void show()" (I suppose they declared it synchronized
because the original show method was synchronized also till JDK 1.1.4). So when
the implementation of the libary class changed, it introduced a deadlock !

I notice that most classes in the Swing library now use internal private monitor
objects - but in spite of that, I always tell the programmers to never really
depend on these implementation specific - so in the code produced in our
company, you will never find a synchronized method unless the Object was built
from scratch by you - and it wasn't meant to be extended. Maybe overkill, but
then seeing production code break due to a change in the library implementation
isn't something I want to see if at all possible.

BK
 
L

Lasse Reichstein Nielsen

[Collections.synchronizedList()]
Ugh, yes!

I'm inclined to think that that wrapper should be deprecated. It doesn't
protect the semantics of the data /in/ the collection, only of the data
structures used internally /by/ the collection.

Well, that sounds like something you *would* like to preserve.
And since protecting the meaning (which can only be done from
outside) will naturally protect the implementation too, there seems
to be little need for the wrapper.

Sometimes a list is just a list :)
/L
 
T

Thomas G. Marshall

Lee Fesperman coughed up:
Thomas said:
Lee Fesperman coughed up:
....[rip]...


Once again, I meant what I said. You snipped a section here without
warning. The section where I show you that your objection to the
terminology I used was without merit. I guess you really didn't want others
to see that.

In usenet, it is /very/ improper to snip out sections without warning,
particularly to make it sound as if the conversation had proceeded without
interruption, when it did not.

The effect is to say that lines of code textually 'exterior' to the
synchronized block are not protected.

I did not say, nor imply that at all.

That is wrong. Code /within/
the block may call methods outside the block even in different
classes, packages and standard API. This code (during the call) will
be synchronized on the synchronization object's monitor.

No kidding. When I say

The execution of such lines of code. Yep

You think it's ok to say that I'm implying that the function calls within
the block are not protected? You think that's somehow not clear that they
are??? When you execute a line of code, you execute it, regardless of what
that line of code entails, which includes method calls. If you think that
needs to be spelled out, you are in the wrong place in usenet entirely.
 
T

Thomas G. Marshall

Bent C Dalager coughed up:
Thomas G. Marshall


Wouldn't it be better if the class

You threw me for a sec. You meant "object". There was discussion of having
the mutex held by the class instead of the object earlier, but I gotcha.

encapsulated the logic needed for
synchronizing itself and then offered this as a general service in its
interface? E.g.,

public Class SuperSyncedThing
{
private int _value;
public int getValue() { return _value; }
public void setValue(int value) { _value = value; }
public void syncedUpdate(Runnable operation)
{
synchronized(this)
{
operation.run();
}
}
}

Now the outside world doesn't need to care what mutex is to be used to
synchronize updates, you'd simply write something along the lines of

final SuperSyncedThing myThing = ...;
myThing.syncedUpdate(new Runnable())
{
public void run()
{
myThing.setValue(myThing.getValue() + 1);
}
});


Well, first, IMHO it /still/ needs to documented to the outside world
precisely what's going on.

For example, within synchedUpdate, the SuperSyncedThing object instance is
holding the mutex. Within that method, it could easily have been the class,
or some other singleton somewhere.

Furthermore, all the calls to setValue() (all by itself) from multiple
threads are no longer thread safe. (assuming that they're using the same
object instance of course). Unless I misunderstood something in your
example. The calls to setValue() are still public, there's no protection
there. Did you mean that all accessor/mutator calls would be required to be
within syncedUpdate() (by convention) ?

By not exposing your mutex to the outside world you are making the use
of your class less low-level and dirty (in my view) and you leave
yourself free to change what mutex to use in the future without
breaking code that was written to use an older version of your class.

(SuperSyncedThing obj).syncedUpdate() is hard coded to using /this/. And
your other methods are not thread safe. (again, unless you enforce their
usage some other way).

Of course, you could get the latter benefit by simply adding a
public Object getMutex();
to the interface, but in my universe that would still leave things
low-level and dirty :)

Yeah, we discussed that. Using /this/ as the holder of the mutex is
certainly useful, as showed already. The biggest issue is in what order you
teach this to students. And, as I strongly urge, that they use the
synchronization block and not the shorthand synchronization method.

(Note that getValue() and setValue() don't have any internal
synchronization

Ah, you got it.

because changing or reading an int is an atomic
operation and so no inconsistencies can occur anyway in this case. At
least, that's the theory ... :)

I don't think that's guaranteed in java. At least I hope it isn't---and I
can't find it in the JLS. ICBW, (I forget) but I think you're not
guaranteed that there aren't X number of operations in bytecode even for an
integer assignment. And even /if/ somehow that were the case, it'd be a
crummy technique fraught with disaster down the road. :)
 
T

Thomas G. Marshall

Bent C Dalager coughed up:
Thomas G. Marshall


That isn't technically correct. Multiple executions of the code _can_
all run at the same time, if the object holding the lock is different
in the different threads.

Yes, of /course/, and this had been pointed out by me and others, over and
over. That's why I'm compelled to re-state that notion needlessly over and
over, like when I said "when done right" above. OI. There is no end to
this... :) I think I'll assign an alt-key to the concept for easy
posting...


....[rip]...

I prefer to look at synchronization as something that "restricts
concurrent access to code in order to protect data or resources".

Ok, there is (usually) a /reason/ for doing things. Restricting
("protecting from") concurrent access to code is the way to that (those) end
(ends).
 
T

Thomas G. Marshall

Chris Uppal coughed up:
I think I've now said all I have to say on this subject, but I did
want to add to:


Ugh, yes!

I'm inclined to think that that wrapper should be deprecated. It
doesn't protect the semantics of the data /in/ the collection, only
of the data structures used internally /by/ the collection. And
since protecting the meaning (which can only be done from outside)
will naturally protect the implementation too, there seems to be
little need for the wrapper. It is just an error waiting to happen...

-- chris


And how would you deal with my example then? Let's make it a little more
general:

// move our thing up x notches...
ourThing.set(ourThing.get() + x); // not thread safe. Kaboom.

/THAT/ is a error waiting to happen (actually it's an error already if
multithreading on a single instance). What would you do? If you create the
following:
 
X

xarax

"Thomas G. Marshall" <[email protected]>
wrote in message /snip/
I don't think that's guaranteed in java. At least I hope it isn't---and I
can't find it in the JLS. ICBW, (I forget) but I think you're not
guaranteed that there aren't X number of operations in bytecode even for an
integer assignment. And even /if/ somehow that were the case, it'd be a
crummy technique fraught with disaster down the road. :)
/snip/

32-bit updates and fetches are atomic. the specification
waffles a little on 64-bit long, although it encourages
implementations to support atomic update/fetch for 64-bit
quantities. also, pointer update/fetch is guaranteed
atomic, regardless of the size. go figure...

there is really no good reason for a jvm implementation
not to support 64-bit atomic update/fetch these days.
 
L

Lee Fesperman

Thomas said:
Lee Fesperman coughed up:
...[rip]...

By 'rip', I assume that means that you are throwing in the towel on finding any useful
case where synchronization is used to protect anything but shared state. Synchronization
is used to protect (control access) to shared state, nothing else.
Once again, I meant what I said. You snipped a section here without
warning. The section where I show you that your objection to the
terminology I used was without merit. I guess you really didn't want others
to see that.

In usenet, it is /very/ improper to snip out sections without warning,
particularly to make it sound as if the conversation had proceeded without
interruption, when it did not.

I was saving a few electrons, since you are loath to back down on even the smallest
detail. You insist, so I'll bother some electrons...

You used "synchronization structure" without a modifier. That is imprecise and
confusing. Java is in the C language family. In the C family, structure without a
modifier refers to a data block. A class in Java is conceptually a structure with
behavior. A better term is synchronization block (referring to a code block), though
synchronized block is really to the point.

I suggested you could have used "synchronization control structure". Control structure
is a term that was used prior to the C family but is accepted in that family as meaning
a code block with associated logic -- for, while, if, and, reasonably, synchronized. You
demurred, even though your usage was inappropriate.
I did not say, nor imply that at all.


No kidding. When I say

The execution of such lines of code. Yep

You think it's ok to say that I'm implying that the function calls within
the block are not protected? You think that's somehow not clear that they
are??? When you execute a line of code, you execute it, regardless of what
that line of code entails, which includes method calls. If you think that
needs to be spelled out, you are in the wrong place in usenet entirely.

Yes it was not clear. You explicitly stated that lines of code not within the block were
not synchronized. Lets ignore reflection for the time being. Given dynamic loading and
dynamic dispatch, there are no lines of code that you can guarantee won't be
synchronized by a synchronization block (except pathologic cases). As usual, you are
splitting the wrong hair.
 
T

Thomas G. Marshall

This is getting far too twisted for me. See ya.


Lee Fesperman coughed up:
Thomas said:
Lee Fesperman coughed up:
Thomas G. Marshall wrote:

Lee Fesperman coughed up:

...[rip]...

By 'rip', I assume that means that you are throwing in the towel on
finding any useful case where synchronization is used to protect
anything but shared state. Synchronization is used to protect
(control access) to shared state, nothing else.
Once again, I meant what I said. You snipped a section here without
warning. The section where I show you that your objection to the
terminology I used was without merit. I guess you really didn't
want others to see that.

In usenet, it is /very/ improper to snip out sections without
warning, particularly to make it sound as if the conversation had
proceeded without interruption, when it did not.

I was saving a few electrons, since you are loath to back down on
even the smallest detail. You insist, so I'll bother some electrons...

You used "synchronization structure" without a modifier. That is
imprecise and confusing. Java is in the C language family. In the C
family, structure without a modifier refers to a data block. A class
in Java is conceptually a structure with behavior. A better term is
synchronization block (referring to a code block), though
synchronized block is really to the point.

I suggested you could have used "synchronization control structure".
Control structure is a term that was used prior to the C family but
is accepted in that family as meaning a code block with associated
logic -- for, while, if, and, reasonably, synchronized. You demurred,
even though your usage was inappropriate.
I did not say, nor imply that at all.


No kidding. When I say

The execution of such lines of code. Yep

You think it's ok to say that I'm implying that the function calls
within the block are not protected? You think that's somehow not
clear that they are??? When you execute a line of code, you execute
it, regardless of what that line of code entails, which includes
method calls. If you think that needs to be spelled out, you are in
the wrong place in usenet entirely.

Yes it was not clear. You explicitly stated that lines of code not
within the block were not synchronized. Lets ignore reflection for
the time being. Given dynamic loading and dynamic dispatch, there are
no lines of code that you can guarantee won't be synchronized by a
synchronization block (except pathologic cases). As usual, you are
splitting the wrong hair.
 
C

Chris Uppal

And how would you deal with my example then? Let's make it a little more
general:

// move our thing up x notches...
ourThing.set(ourThing.get() + x); // not thread safe. Kaboom.

/THAT/ is a error waiting to happen (actually it's an error already if
multithreading on a single instance). What would you do? If you create
the following:

class MyClass
{
private int ourThing thingness = 0;
public synchronised get() { return thingness; }
public synchronised increment(int by) { thingness += n; }
// TODO: is this really needed ?
public synchronised set(int n) { thingness = n; }
}

but it's doubtful whether I'd provide a public set() method unless there was
clear need for both set() and increment() as public operations.

Put into my terms. Instances of MyClass accept responsibility for ensuring
that they can be increment()-ed in a thread-safe manner. It is not the
/caller's/ responsibility to do so.

You may notice that this leads to broadening of the interface of MyClass -- I'm
entirely happy with that. Such broadening is (IMO) natural in decent OO code.
(As an aside, much Java code is not -- in this specific sense, and IMO -- very
well written. The received wisdom is to keep classes lean, and to put the
logic in the caller. But I think that just leads to a mess where
responsibility does not properly follow object boundaries.

-- chris
 
C

Chris Uppal

Lee said:
Thomas G. Marshall wrote:
...[rip]...

By 'rip', I assume that means that [...]

I think Thomas uses "rip" where another would use "snip". I admit that when I
first saw it, I took it as insulting -- something like "we don't need all
/this/ crud".

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,481
Members
44,900
Latest member
Nell636132

Latest Threads

Top