Object-oriented multithreading
{ if somebody has links to google groups repository or at least the
subject lines of the threads discussing this in c.p.threads, do post
them please, for the benefit of both the OP and the group, and so we
don't begin discussing what has already been discussed. thanks! -mod }
Over on comp.std.c++, there's a thread about what form
multithreading support in a future C++ language standard
would take.
One of the big issues is synchronization, especially
of memory reads and writes. For example, if we have
int shared_value = 0;
Mutex shared_value_mutex;
....
void thread_a() {
shared_value_mutex.lock();
shared_value += 10;
shared_value_mutex.unlock();
}
void thread_b() {
shared_value_mutex.lock();
shared_value += 20;
shared_value_mutex.unlock();
}
and we assume that thread_b() starts before thread_a()
finishes, it is conceivable that thread_a() will release
the mutex, and thread_b() will get it, before thread_a's
update of shared_value propagates to the processor running
thread_b.
(Keep in mind that in a thread-unaware system, no operation
can be assumed to be atomic.)
The only safe way to deal with this is to:
a. do all updates of shared variables via library functions,
in addition to protecting critical sections with mutexes,
or:
b. provide a language-defined way to tell the compiler that
a given synchronization variable or operation protects
a given set of variables.
In reading and thinking about this, it occurs to me
that, in my (possibly limited) experience, synchronization
always comes down to having a single thread be able to make a
set of updates to a set of related variables without another
thread updating the same variables in the meantime.
Another way to think of it is that we want some set
of operations to be "atomic" with respect to the variables
they reference/update.
If we think in object-oriented terms,
"set of related variables" = object
"set of updates" = method.
Seen this way, the logical unit of data to protect is
an object, and the logical unit of code for an atomic
operation is a method.
Following this approach, we would handle synchronization
of operations by declaring a member function "atomic",
or have some sort of lock function that would apply to
*this.
The compiler would recognize this construct as meaning
that before a thread could start the function, it would
have to wait:
a. to obtain exclusive access to *this (e.g., by locking an
instance-specific mutex), and
b. for all memory writes to *this to have completed,
or at least to have become visible to this thread.
I don't recall seeing this approach mentioned in this group
or comp.std.c++; I don't follow the multithreading groups
closely enough to know if this has come up there or not.
Has this approach been considered? If so, has it been discarded
as a Bad Idea, and, if so, why?
The main objection that I can think of that I can't
easily dispose of (to my own satisfaction, at least)
is that there are forms of synchronization that
don't easily fit into an "atomic member function" model.
(Another objection would be that as presented here,
it only has lock/wait, not lock/fail, but I think that
a way could be found to express this.)
Or am I asking an FAQ?
-- Alan McKenney
[line eater fodder]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]