[cpp-threads] Whence Sequential Consistency?
Jeremy Manson
jmanson at cs.umd.edu
Fri Jan 19 03:11:15 GMT 2007
I can answer this for Java; I believe that the C++ case is a little more
complicated, but substantively the same.
In Java, we made a clear decision to pursue certain properties of
programs. We built it on some notions that are fairly common in the
literature:
1) We say that two accesses conflict if they are accesses to the same
shared variable, and at least one is a write.
2) When two conflicting accesses are not ordered by happens-before in a
particular execution of a program, they are said to be in a data race.
3) If, in all sequentially consistent executions of a program, there are
no data races, then the program is said to be "data race free".
4) We guarantee sequentially consistent behavior for all data race free
programs.
So, in short, all you have to do is make sure that your conflicting
accesses are ordered by happens-before, and you get sequential
consistency as a guarantee of the program. It is unnecessary to
guarantee that individual program instructions (like CAS) provide
sequential consistency: only that they provide happens-before.
An example, using Java's volatile, which is sounding less and less as if
it will be SC:
Let's say int x = 0 and volatile int v = 0
Thread 1:
x = 1;
v = 1;
Thread 2:
r1 == v;
if (r1 == 1) {
r2 = x;
}
There is a happens-before relationship between every write to a volatile
variable, and every read that sees the value that was written. Thread 2
will only read from x if it sees 1 for v, in which case there was a
happens-before relationship between the write to v in Thread 1 and the
read of v in Thread 2. Therefore, there can be no accesses of x in an
execution of this program that are not ordered by the happens-before
relationship -- no data races. Because this program is data-race-free,
it will behave in a sequentially consistent fashion.
I believe that this high-level intuition maps pretty easily to low level
implementation. Does that go any distance to answering your question?
Jeremy
Lawrence Crowl wrote:
> Something about sequential consistency has been bothering me for a
> while, and I am not sure how to articulate the problem, but I will
> give it a shot.
>
> Where does sequential consistency come from?
>
> The prevailing notion is that atomic operations are not (necessarily)
> sequentially consistent, but that the equivalent locked code is.
> How is this so?
>
> If locks are implemented with atomic operations, then it does not
> seem to me that sequential consistency would be an emergent property
> of locks, which then implies that it is a defined property of locks.
> If so, then no one could write a new lock using pure C++. They would
> have to use platform-specific techniques, which would surely inhibit
> development of new locks.
>
> More importantly, a difference in sequential consistency between
> locks and atomics implies that a programmer _cannot_ replace a
> poor-performing lock-based data structure with a lock-free data
> structure. The reason is that sequential consistency became an
> implied property of the locked data structure and removing that
> property would throw unknown numbers of clients into the land of
> undefined and untested behavior.
>
> An important property of programming languages is interface
> invariance. It ought to be possible for the implementation of an
> interface to change without changing the properties of the interface.
> So, if locks and atomics have different sequential consistency
> properties, how do I not get sequential consistency by adding locks?
> How do I preserve sequential consistency when removing locks?
>
More information about the cpp-threads
mailing list