views:

1384

answers:

6

Does asynchronous call always create a new thread?

Example:

If Javascript is single threaded then how can it do an async postback? Is it actually blocking until it gets a callback? If so, is this really an async call?

+8  A: 

The Javascript model is single-threaded. An asynchronous call is not a new thread, but rather interrupts an existing thread. It's analogous to interrupts in a kernel.

Yes it makes sense to have asynchronous calls with a single thread. Here's how to think about it: When you call a function within a single thread, the state for the current method is pushed onto a stack (i.e. local variables). The subroutine is invoked and eventually returns, at which time the original state is popped off the stack.

With an asynchronous callback, the same thing happens! The difference is that the subroutine is invoked by the system, not by the current code invoking a subroutine.

Jason Cohen
+4  A: 

In many GUI applications, an async call (like Java's invokeLater) merely adds the Runnable object to its GUI thread queue. The GUI thread is already created, and it doesn't create a new thread. But threads aren't even strictly required for an asynchronous system. Take, for example, libevent, which uses select/poll/kqueue, etc. to make non-blocking calls to sockets, which then fires callbacks to your code, completely without threads.

Sean
+23  A: 

This is an interesting question.

Asynchronous programming is a paradigm of programming that is principally single threaded, i.e. "following one thread of continuous execution".

You refer to javascript, so lets discuss that language, in the environment of a web browser. A web browser runs a single thread of javascript execution in each window, it handles events (such as onclick="someFunction()") and network connections (such as xmlhttprequest calls).

<script>
function performRequest() {
  xmlhttp.open("GET", "someurl", true);
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4) {
      alert(xmlhttp.responseText);
    }
  }
  xmlhttp.send(sometext);
}
</script>
<span onclick="performRequest()">perform request</span>

(This is a nonworking example, for demonstration of concepts only).

In order to do everything in an asynchronous manner, the controlling thread has what is known as a 'main loop'. A main loop looks kind of like this:

while (true) {
    event = nextEvent(all_event_sources);
    handler = findEventHandler(event);
    handler(event);
}

It is important to note that this is not a 'busy loop'. This is kind of like a sleeping thread, waiting for activity to occur. Activity could be input from the user (Mouse Movement, a Button Click, Typing), or it could be network activity (The response from the server).

So in the example above,

  1. When the user clicks on the span, a ButtonClicked event would be generated, findEventHandler() would find the onclick event on the span tag, and then that handler would be called with the event.
  2. When the xmlhttp request is created, it is added to the all_event_sources list of event sources.
  3. After the performRequest() function returns, the mainloop is waiting at the nextEvent() step waiting for a response. At this point there is nothing 'blocking' further events from being handled.
  4. The data comes back from the remote server, nextEvent() returns the network event, the event handler is found to be the onreadystatechange() method, that method is called, and an alert() dialog fires up.

It is worth noting that alert() is a blocking dialog. While that dialog is up, no further events can be processed. It's an eccentricity of the javascript model of web pages that we have a readily available method that will block further execution within the context of that page.

Jerub
suggest an edit of the answer "It is worth noTHing"is different to "it is worth noTing"which I think is your intent. Just to avoid confusion for readers
MadMurf
@MadMurf: I noticed that too....and fixed it.
Mark
+1  A: 

A couple notes about JavaScript in particular:

XMLHttpRequests are non-blocking by default. The send() method returns immediately after the request has been relayed to the underlying network stack. A response from the server will schedule an invocation of your callback on the event loop as discussed by the other excellent answers.

This does not require a new thread. The underlying socket API is selectable, similar to java.nio.channels in Java.

It's possible to construct synchronous XMLHttpRequest objects by passing false as the third parameter to open(). This will cause the send() method to block until a response has been received from the server, thus placing the event loop at the mercy of network latency and potentially hanging the browser until network timeout. This is a Bad Thing™.

Firefox 3.5 will introduce honest-to-god multithreaded JavaScript with the Worker class. The background code runs in a completely separate environment and communicates with the browser window by scheduling callbacks on the event loop.

Matthew
+1  A: 

No, but more than one thread will be involved.

An asynchronous call might launch another thread to do the work, or it might post a message into a queue on another, already running thread. The caller continues and the callee calls back once it processes the message.

If you wanted to do a synchronous call in this context, you'd need to post a message and actively wait for the callback to happen.

So in summary: More than one thread will be involved, but it doesn't necessarily create a new thread.

izb
+1  A: 

I don't know about javascript, but for instance in the Windows Forms world, asynchronous invocations can be made without multiple threads. This has to do with the way the Windows Message Pump operates. Basically a Windows Forms application sets up a message queue through which Windows places messages notifying it about events. For instance, if you move the mouse, messages will be placed on that queue. The Windows Forms application will be in an endless loop consuming all the messages that are thrown at it. According to what each message contains it will move windows around, repaint them or even invoke user-defined methods, amongst other things. Calls to methods are identified by delegates. When the application finds a delegate instance in the queue, it happily invokes the method referred by the delegate.

So, if you are in a method doing something and want to spawn some asynchronous work without creating a new thread, all you have to do is place a delegate instance into the queue, using the Control.BeginInvoke method. Now, this isn't actually multithreaded, but if you throw very small pieces of work to the queue, it will look like multithreaded. If, on the other hand you give it a time consuming method to execute, the application will freeze until the method is done, which will look like a jammed application, even though it is doing something.

Rui Craveiro