Concurrency, was Re: Doh! Stupid Programming Mistakes <humor>
bryan.sant at gmail.com
Thu Oct 26 10:23:24 MDT 2006
On 10/25/06, Levi Pearson <levi at cold.org> wrote:
> I am one? I am one what? Are you disagreeing that memory protection
> is orthogonal to concurrency?
Oh, don't play dumb. You know what I mean.
(I'm just messing with you).
I'm not disagreeing that there are two distinct issues with
concurrency. My earlier post made the suggestion of using threads in
tandem with a high-level language that provides proper memory
protection and heap data scope isolation. Given this situation I find
that the built-in protection of OS processes is unneeded. There are
trade-offs with both approaches - child-processes and threads.
However, as stated before, I find all of the benefits of processes in
threads plus the *option* to expose shared heap data and interact
efficiently when that makes sense. The one thing that separate
processes gives you that threads do not is a fresh user-land virtual
address space of 2-3GB (depending on kernel config) on a 32-bit system
-- on a 64-bit system the need for extra processes for additional
memory space is unnecessary.
> Of course you can choose not to take advantages of dangerous
> features. That's not the point. You're saying that threads are the
> best solution to all problems. I'm saying there are alternative
> concurrency models that provide additional safety from inadvertent
> errors. I don't see what your problem with this idea is.
It's not a matter of not choosing to take advantage of dangerous
features, it's a matter of higher-level languages providing similar
protection that the OS would provide via processes. I think there is
tremendous value in the protection processes give you. I'm not
disagreeing with your assertion that protection, even over-protection
is good. It is good. It's just provided by a different mechanism
than the OS in my case, and I find the model I work with to be more
convenient and flexible.
> Right. Like I said, some high level languages (read, Java) help out
> a lot.
I'm sure C# and others do this too. I've never written concurrent
software with C# or Perl. Do they have similar features for
threading? If so, I would choose threads over processes in those
high-level languages as well.
> One can always choose the best tool for the job, too. Assembly
> Language can express any computation that Java can, yet sometimes we
> choose to write programs in Java. Probably because of the increased
> safety, abstractions, and other good things.
You are exactly right. Increased safety and abstraction is the
primary reason for using a higher-level language. You're no doubt
drawing a similarity between these added protections and the
protections of using child processes. I think that protection is
good, but only needed if you're using a language/runtime that doesn't
provide an even better model for concurrency.
> The point of abstraction is to hide irrelevant details. If it ends
> up hiding important details instead, it creates more headaches and
> bugs than it prevents. See the following:
> I believe the Java memory model has been fixed now; I'm sure you'd
> know better than I do.
It has been fixed in Java 5, and even prior to Java 5 this was only an
issue when trying to use a certain optimization during lazy
instantiation of a shared object. In any case, my point is that if
you are concerned about the details of mutil-thread interaction you
can always use a thread in exactly the same manner you would use a
child-process (don't share any heap data and don't do any locking) and
you're no better of worse off. So you can't say processes are good
and threads are bad because there are extreme examples of how to break
yourself when using threads in an exotic way.
> I'll assume you've momentarily forgotten about the non-composability
> of locks. You can't take two arbitrary, correct pieces of lock-based
> software, compose them, and assume the result is correct. This
> describes the problem better than I could:
Woopie-doo. Again, they are talking about the possible complexities
of locks in highly threaded applications. I'm not saying that working
with locks can't become complex, but your alternative of using
child-processes doesn't solve the problem either. If your
highly-concurrent application requires frequent interaction between
threads/processes, then that's what it needs. Using processes will
not solve this locking/interaction problem -- in fact it just avoids
it all together or has to supplement it with IPC (and now your back to
managing the race/dead-lock problems with the shared state data in
your main process). As you mentioned before, on Linux, threads and
processes are almost identical. About the only difference is that
threads MAY access shared heap data while processes never can. So
with threads you can choose to use locks and shared data sparingly
with much success and far higher interaction performance than
processes. That's my main point. Threads aren't evil and dangerous
compared to processes when using high-level languages.
> This isn't a matter of fear, it's a matter of managing complexity.
No, it's a matter of fear. You are a scaredy-scaredy cat. Meeeeooooowwww.
(Again, I'm just joking around, please don't ever take my posts too seriously).
> It is very easy to keep your program safe and correct by over-
> protecting your resources. That will, however, slow the program
> down. As you make your locks increasingly fine-grained, it becomes
> increasingly difficult to reason about the correctness of your
> program. This is just the way it is, whether you are cowardly or
> brave. Turning down tools that help manage this complexity is
> neither brave nor cowardly; it is stupid.
I agree. This is why I use Java instead of C and child-processes. The
protection is worth it, and it this case, is more performant too.
> I've read from people far smarter and more experienced than I am, and
> quite possibly smarter than you, hard as that may be for you to believe.
Hard to believe? You mean impossible to comprehend!!! Not only am I
brilliant, but I'm incredibly humble too!
> > That's true by virtue of the fact that a thread can be used just like
> > a child process but the reverse is not true. Threads give you the
> > option to touch shared data -- not an obligation to do so. Child
> > processes restrict your options.
> Encapsulation via private class members restricts your options, too.
> So does restricting memory allocation and deallocation to the runtime
> system. You seem to be okay with those restrictions, which were
> largely added for reasons of safety and maintainability of software.
> Safer concurrency models provide a similar tradeoff.
No, now you're just avoiding my point. With encapsulation I have fine
grained control over the data I will or will not expose. Likewise
with threads I have control over what data I will or will not expose.
With processes, I am not able to expose any shared data period. This
is an absolute restriction. That's only a feature if your program
doesn't require any interaction with the parent or other processes.
In my experience this isn't a typical situation. You almost always
need SOME level of interaction between a controlling thread (parent
process) and it's worker (child process).
> This is clearly better than the state of things in C, but it's far
> from the best we can do. But you can continue to use what you've got
> in Java if you really believe it's the best that can be.
I don't believe that Java's threading model is the best that could be,
but I do find it more than worthy to utilize in the face of existing
alternatives today. Given Java's model (an others who have similar
capabilities), I don't find any virtues in the child-process model of
concurrent programming compared to threads. But I do appreciate this
discussion, I find your opinions to be very sound and well thought
out. You are a true thinker and I appreciate your insights and
opinions. I hope I haven't been too offensive with my pseudo insults
More information about the PLUG