Shared memory parallel machines have existed since the 1960s and, with the proliferation of multi-core processors, shared memory parallel programming has become increasingly important. Unfortunately, some fairly basic questions about parallel program semantics have not been addressed until quite recently. Multi-threaded programming languages are on much more solid ground than they were as recently as a decade ago. Nonetheless a number of foundational issues have turned out to be surprisingly subtle and resistant to easy solutions. We briefly survey three such issues:
1) All major programming languages support atomic operations that enforce only very weak memory ordering properties. These implicitly rely on enforcement of dependencies to preclude certain "nonsensical" outcomes.
Unfortunately, we do not know how to define a suitable notion of dependency.
2) Garbage collected programming languages such as Java, rely on finalization, most commonly to interact
correctly with non-garbage-collected parts of the system. But finalization raises largely unsolved concurrency
issues. As a result, almost all interesting uses of finalization uses are subtly, but seriously, incorrect.
3) It can be difficult to avoid object destruction or memory deallocation races in-garbage-collected languages like C++. As a result, async(), the basic C++11 thread spawning facility has surprisingly complex semantics, with unintended consequences.