2

Imagine any object oriented PL based around the idea of message sends: some method basically performs something like this:

send(target=someTarget, sender=self, message=someMessage)

Also, most of the PL allow for async message communications, where you can issue multiple messages to multiple targets and then "yield" to scheduler.
My question is: are synchronous communcations a subset of asynchronous ones?
In my head you can break down any synchronous message send into something like this:

asyncSend(target=someTarget, sender=self, message=someMessage)  
target.setNotify(self)  
self.setBlocked()  
yield

Which will be totally aquivalent to a synchronous message send, BUT:

The problem I currently see if you try to mix these two together. When some method issues an async message send and then, before yielding, performs a synchronous message send, which gets kinda messed up. Hence the question :)

Also, sorry if this is wrong stackexchange. I don't think this question applies to the usual SO.

EDIT1: rephrasing the question: which of both concepts is more general? can you even say that?

artemonster
  • 379
  • 2
  • 9

1 Answers1

3

There are several possible semantics for asynchronous message passing, so there isn't a single answer to this question. It depends how the scheduler works.

From a theoretical perspective, the simplest model (for some version of simple) is to not have a scheduler. Once a message has been emitted, it may be received at any time when the receiver is ready. All the parts of the system work in parallel. This is the principle of process calculi, of which there is a rich theory.

The notion of synchronicity then depends on what the continuation of a send operation is. In the pi calculus, which is arguably the most important model of concurrency, sending is a synchronous operation, with a continuation. $\bar a\langle x\rangle.P$ (“send $x$ on $a$ then do $P$”) blocks until some other part of the system is ready to receive a message on $a$. An asynchronous send operation is represented by doing the send in parallel with something else:

asyncSend(target=a, message=x);
stuff();

is represented by $(\bar a\langle x\rangle. 0) \mid \mathtt{stuff}$ (send $x$ on $a$, then do nothing; all of this in parallel with stuff).

The join calculus is another process calculus inspired from the pi-calculus. It defines both asynchronous and synchronous messages. Synchronous messages act like function calls — they're remote procedure calls. Asynchronous messages have no continuation: once the order to send the message has been given, the message will sit around until it gets received; the only way to know that the message has been received is to take action on the receiver. The snippet above is represented by $a\langle x\rangle \mid \mathtt{stuff}$. The notation $a\langle x\rangle$ means “send $x$ asynchronously on $a$”; there's no continuation for the send operation: $\color{red}{a\langle x\rangle; Z}$ is not even syntactically valid. A synchronous call can be encoded with asynchronous calls by having the receiver reply. If the receiver sends an acknowledgement: $$ a\langle x\rangle \mapsto \mathtt{ack}\langle\rangle \mid \ldots$$ then the sender can wait for this acknowledgement: $$ a\langle x\rangle \mid (\mathtt{ack}\langle\rangle \mapsto \ldots) $$ models

syncSend(target=a, message=x);
...

In the join calculus, synchronous and asynchronous operations are distinguished in the syntax. Therefore there's no possibility of “getting messed up”.

The mess comes from trying to force concurrent behavior into a sequential framework. Since you mention object oriented languages (which have absolutely nothing to do whatsoever about asynchronous message passing), you're probably thinking of implementations of these concepts in languages like Java and C#. I'm not familiar with those libraries, but as far as I know, they introduce additional complications by forcing the programmer to be explicit about threads. Threads are not a natural concept in process calculi: if things happen in a certain order, it's because of how the information is propagated, not because the language describes how a scheduler will do its job. A call like asyncSend may have additional constraints on when it takes place relative to other things that are going on in the same thread. If there is some constraint between an asynchronous send and a subsequent synchronous send, that's a limitation of the library which defines when the asynchronous send may take place. A true asynchronous send would not have such a constraint.

Gilles 'SO- stop being evil'
  • 44,159
  • 8
  • 120
  • 184