Every concurrency API needs a way to run code concurrently. Here’s some examples of what that looks like using different APIs:
go myfunc(); // Golang pthread_create(&thread_id, NULL, &myfunc); /* C with POSIX threads */ spawn(modulename, myfuncname, ) % Erlang threading.Thread(target=myfunc).start() # Python with threads asyncio.create_task(myfunc()) # Python with asyncio
There are lots of variations in the notation and terminology, but the semantics are the same: these all arrange for myfunc to start running concurrently to the rest of the program, and then return immediately so that the parent can do other things.
Another option is to use callbacks:
Again, the notation varies, but these all accomplish the same thing: they arrange that from now on, if and when a certain event occurs, then myfunc will run. Then once they’ve set that up, they immediately return so the caller can do other things. (Sometimes callbacks get dressed up with fancy helpers like promise combinators, or Twisted-style protocols/transports, but the core idea is the same.)
And… that’s it. Take any real-world, general-purpose concurrency API, and you’ll probably find that it falls into one or the other of those buckets (or sometimes both, like asyncio).