Hi Eamonn,
Definitely not a dumb question! This kind of thing is the topic of a great deal of argument and differing opinions from smart people. :)
I don't know much about how the Go implementation works -- I imagine due to the nature of Go, it's more likely to utilize multiple threads. As Ian points out, by default a capability server in the Go implementation will only accept one method call at a time, but you can call server.Ack() at the start of the method to "unblock" the next call to happen concurrently.
In Cap'n Proto's C++, I made the design decision to focus on single-threaded event loops, because the synchronization involved in allowing multiple threads access the same objects is not just difficult to get right, but also expensive. In C++, the right way to build a multi-threaded server is to create a separate event loop in each thread. Any particular RPC connection -- and all the calls and objects associated with it -- will have to be owned by one particular thread and handled there, but different connections could potentially be distributed across different threads.
In the future, I'd like to extend KJ so that event loops in separate threads can signal each other more easily. (Currently, you more-or-less have to create a socketpair to communicate between threads.) I'd also like to implement Cap'n Proto's 3-party handoff protocol. Perhaps this could allow threads to seamlessly "hand off" to objects in other threads, with the caveat that the client will need to form a new connection to the new thread.
I don't expect the C++ implementation will ever allow multiple threads to share a single event loop or handle events from a single connection. The synchronization complexity is just too high for that.
-Kenton