You wait on a shared channel so both read and sleep threads queue a message when ready (whichever comes first). Not sure about channels, but in other languages it would be a concurrent queue.
This won't cancel the read, it'll just ignore the result
Most languages I know allow killing a thread, or at least unblock a system call.