Coroutines allow performing concurrent operations without threads by using continuation-passing style and suspension functions. Coroutines are lightweight and efficient compared to threads. Behind the scenes, coroutines use a state machine and continuation objects to pause and resume computation across suspension points, providing an appearance of concurrency through asynchronous operations.