Well, no, you're just writing the locks yourself in an ad-hoc way. Every time you have a callback calling another callback, you have a lock and all the race condition/deadlock issues associated with that. Of course, writing an application that doesn't have complicated synchronization requirements (streaming fileserver) can often require less boilerplate in an evented system. However, you run into a catch-22 here: by definition it's an application with fewer synchronization requirements, so you'd have to use fewer complicated locks in a 'heavy thread' implementation as well :).
Ultimately it's an engineering tradeoff problem, and you have to weigh lightweight node-style cooperative multitasking with the ability of a traditional thread system to better handle highly complicated scenarios.
Or you can be Russ Cox and argue that this is a false dichotomy[1] and that we should all be using CSP. I'm in that camp.
Andrew Birrell: threads.
John Ousterhout: events.
John DeTreville: no.
Rob Pike: yes.
So how do you handle concurrency without race conditions without using isolated processes or pure message passing? Ok so you don't have thread locks, big deal, but you still have shared data structured that could be updated in a non-deterministic order depending on which file descriptor gets fired first by epoll (or whatever select thingy is being used lately).
ummmm, can someone elaborate? I don't understand that statement.