The question duplicates the topic of the question asked here.
I would like to ask for some additional clarification with respect to a different point of view.
in distributed computing, memory coherency is in the end implemented using message passing over network channels, with distributed locking and so forth. Message passing, IIUC, would not always eliminate concurrency, except at the very low level, because the processes still usually affect each others state. And they do so, in what they believe to be consistent way.
For example, a simple command interpreter can be implemented on top of message passing, and the commands can be sent as part of several remote transactions executed in parallel from multiple conversant processes. So, high level interactions would require design for concurrency in most cases. That is, IMO, it is very unlikely that processes have no transaction semantics of long term operations.
Additionally, sending a message, with a value in consistent state does not guarantee correctness. It is important, how this value is produced and what happens in between the messages that provided the input data and the messages that publish the transformed result.
On the other hand, low level interactions with physical memory are always essentially some kind of message passing over buses. So, at the lowest level, sharing memory and message passing are identical.
And at the per-instruction level, the atomicity of aligned loads and stores is usually guaranteed. So, the distinction is still blurry to me.
In prose, how does the choice of the shared memory vs message passing relate to concurrency? Is it just a matter of choice of technical pattern to solving concurrency, and mathematical model for defining and analyzing interactions of parallel processes, or are those techniques also architectural patterns that when applied systematically, fundamentally affect the concurrency issues in the system?
Thanks.
Edit (some additional remarks):
Apparently, the two methods are distinguished by correctness and performance. But I have the following problems with this distinction.
I know that messages can act like transfers of big scattered virtual datums. However, the "by-value" approach does not guarantee consistency without synchronization beyond the atomic read of non-unitary (or procedurally generated) logical datum. By consistency, I imply something like causality or sequential ordering of the changes, etc. With message passing, indeed, every process only mutates its own memory. A process acts just like a controller to its private memory. This is like sharing on top of message passing, serialized by the process owning the datum, but on a MESSAGE-BY-MESSAGE basis (similar to how memory serializes on a word-by-word or cache-line-by-cache-line basis). It remains responsibility of the application programmer to guarantee synchronization of the transactions involved in sending the messages. Namely, that messages to one process, from multiple conversant processes, must be sent in consistent order corresponding to the semantics of the operations those processes are executing. May be with control messages to the owning process, or through coordination directly between the contenders, but some restriction to the concurrency of the messages should be most likely necessary.
Sharing memory can be indeed faster for local inter-process communication (ignoring contention), but why would this be the case for cross-machine communication? Shared memory for distributed computing is implemented on top of the network communication. So, shared memory, aside from caching benefits, can not be faster.
The techniques are obviously different. What I can't seem to understand is how they can be broadly compared to each other, when there is nothing intrinsically beneficial to either one. One must assume what the platform supplies, and what the software tries to accomplish, and such assumption can not be universally true.