Есть много способов решить эту проблему; у каждого свои недостатки.
Например, «пут» может порождать новый поток каждый раз. Таким образом, вам вообще не понадобится буфер. Если поступает много запросов, вы создаете много потоков, пока ваш ЦП не будет больше занят переключением между потоками, чем их выполнением. Но это просто перемещает проблему из вашего кода в ОС: в определенный момент вам всегда нужно синхронизировать доступ к переменной в памяти. ОС должна поддерживать список потоков, и доступ к этому списку должен быть синхронизирован.
Либо вы хотите ограничить количество потоков (тогда «пут» должен иметь возможность читать переменную, в то время как потоки могут завершаться одновременно и уменьшать ее -> снова синхронизированный доступ). Или вы рискуете исчерпать ресурсы, потому что у вас слишком много потоков.
Вы можете отправить сообщение, когда вызывается «put», и потребители могут прослушать сообщение. Но это только сложный способ реализовать «ожидание» потоков. И вам нужен способ убедиться, что только один потребитель получит сообщение. Опять же, вам понадобится некоторая синхронизированная структура данных.
Итак, в конце концов, проблема заключается не в назначении, а в параллельном доступе к одной переменной, и независимо от того, как вы пытаетесь, для любой реализации продукта-потребителя, вы должны быть в состоянии сделать это (или все будет однопоточным).