Re: Threads - When?
Lourens Veen wrote:
Personally, if there was a way to do it, I'd much rather not think
about thread synchronisation while I'm coding my app. I'd much rather
say "X needs to be done" and let the compiler figure out how to
divide that task across the (potentially dozens or hundreds of)
available cores.
C++ covers a wide range of abstraction levels, from all the way down
to raw pointers and bit fields to very abstract things like
Boost.spirit, and everything in between. At lower levels threading is
definitely an issue to be reckoned with, but it would be nice if we
could eradicate it from the higher levels of abstraction and use a
more declarative style of programming there.
Generic programming can help there, and C++ is good at that. The STL
already allows parallel implementations of applicable algorithms on
containers for example.
Hi Lorurens,
You certainly have my empathy regarding ease-of-use.
Yet, if I thought that were something that the language could do to
help with threading by way of say, adding keywords or operators, I
would support it enthusiastically. But as I mentioned in another post,
I think if such keywords where "invented", there would be an extremely
strong parallel between the use of those keywords and the use of
library calls that do the same thing. Note that implicit in my view
is that the "I just need something to happen" mentality will not work
with multi-threading. Threading is just about being able to spawn and
kill new threads. Nor is it only about preventing simultaneous access
to state. It goes far beyond that.
What many in this group is doing (including myself sometimes) is mixing
"multi-threading" with synchronization.
Multi-threading means just that. You can have multiple threads. But
this does not necessarily imply synchronization. You could have 10
threads working on 10 global objects, 1 object per thread, and never
need to think about synchronization. No mutexes needed.
Or you could have one thread only in an application, that blocks into a
GUI message is placed into the Window message queue of WIN32K.SYS in
Microsoft Windows. Here, there is only one thread, but you need an
event, and the part of the system that is not yours, the part that
controls the queues, has a spin-lock backed by a mutex.
Or you can have system that mixes both threading and synchronization.
One thing that I know for myself is that threading/synchronization
*requires* conscious design. This is a system design issue. That your
poor global variable got trampled on because you did not protect it
with a mutex is not simply a practical "inconvenience". People who use
semaphores on queues and mutexes on global state are not simply trying
to serialize access. They are organizing processes, as in flows of
execution, deliberately coordinated with deliberate control. The same
thing goes on in a chemical factory - you _must_ think from a systems
mentality. You must be cognizant of the reason you have multiple
threads in the first place.
I would not call my threading experience spectacular, but I wrote my
first kernel-mode preemptive multi-tasker on an iAPX 80386 in assembler
and C in 1989, and I have been using Windows threading and
synchronization daily at since 1998, and I I can tell you from my own
experience: there is no magic to be had. I think the only way to share
my point of view is to write a lot of threading applications. I am not
saying that programmers here have not. Frankly, I have no idea what
threading experience people here have, but based on posts about
multiple CPU's, the post about spin-locking being efficient, etc...I
get the feeling that it is not something that they do every day.
As far multiple processors and multiple cores, that is handled
automatically. The engineers at Intel, Freescale, ARM, IBM, National
Semiconductor, MIPs...when they design these chips, they spend much
time anticipating how they will be used, both by the general programmer
and by the OS writer who has to support all the things that a
multi-tasking OS is expected to support (optimal switching,
mutual-exclusion, paging, life-time management, kernel-mode exceptions,
double-preemption, the list is endless). If you look at the original
architecture of the 80386, for example, you will see that they not only
anticipated how things should be, but also accommodated the legacy
system by providing the option of segmentation and page, the registry
set, the curiously convenient word that could be used to locate a page
in the swap file on hard disk that just happened to be *EXACTLY* the
right size you would want....these engineers know what we need. They
anticipate _very_ well, so the result is that, if you write against the
API that is provided by your compiler, you will hardly ever have to
worry about these things. The know that, if it happens that there CPU
is being used in a 4-way or 8-way system, the average programmer would
really rather not care about that. If it *does* happen that you have to
start consciously thinking about cores, they are not going to let you
find out the hard way. They will simply tell you, in the reference
manuals.
To give another example, am typing this post on a dual core machine.
Another machine I had a few months ago was a multiway AMD. Not once
did I give a thought about the cores. Multi-threading, the kind that
90%+ of programmers want, is old hat. The need to be conscious of the
design of system-wide synchronization is not going to be obviated by
the language.
My suggestion: Write some multi-threading code (if you have not
already) :)
If you have a multi-threading application, feel free to send me a
description (even something vague would be OK), and I will post here a
design description that shows that it can be done elegantly and
robustly in the context of the existing language using synchronization
primitives.
-Le Chaud Lapin-
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]