One of the things that Go (and Erlang, among others) got right was using channels as the main mechanism for synchronizing and communicating between threads. This post describes a minimal, portable (as in based on bordeaux-threads) implementation in roughly 100 lines of Common Lisp. I suspect there are plenty of more elaborate implementations out there. The point of this exercise is cutting the idea down to it's core; for educational reasons, and because I prefer more focused code than what's generally offered.
A channel needs a fifo queue to buffer items, the most obvious way to get there in Common Lisp is a list that keeps track of it's tail.
The easiest way to keep track of buffer length and block threads on access when needed is to use semaphores. The most popular thread implementation in Common Lisp, bordeaux-threads, unfortunately lacks semaphores. Luckily, it provides locks and condition variables; which is all we really need.
A channel is defined as a locked fifo queue that uses two separate semaphores for controlling access. Both semaphores share the same lock as the queue.
You may find a full implementation of these ideas and more here, multi-threaded generators is the best current example of channel use. And feel free to join the ongoing discussion on Hacker News.