Можно разделить ресурс между потоками, вообще не используя блокирующие блокировки, если ваш сценарий соответствует определенным требованиям.
Вам нужен примитив для обмена атомарными указателями, например, Win32 InterlockedExchange . Большинство процессорных архитектур обеспечивают некоторый атомарный обмен, и обычно он намного дешевле, чем получение формальной блокировки.
Вы можете хранить свою очередь рабочих элементов в переменной-указателе, которая доступна для всех потоков, которые будут в ней заинтересованы. (глобальная переменная или поле объекта, к которому имеют доступ все потоки)
В этом сценарии предполагается, что участвующим потокам всегда есть чем заняться, и лишь изредка «заглядывают» на общий ресурс. Если вам нужен дизайн, в котором потоки блокируют ожидание ввода, используйте традиционный объект события блокировки.
Прежде чем что-либо начнется, создайте свой объект списка очередей или рабочих элементов и назначьте его переменной общего указателя.
Теперь, когда производители хотят вставить что-то в очередь, они «получают» эксклюзивный доступ к объекту очереди, обменивая значение NULL на переменную общего указателя с помощью InterlockedExchange. Если результат обмена возвращает ноль, то кто-то еще в настоящее время модифицирует объект очереди. Sleep (0), чтобы освободить оставшуюся часть времени вашего потока, затем цикл, чтобы повторить своп, пока он не вернет ненулевое значение. Даже если вы закончите цикл несколько раз, это много. во много раз быстрее, чем вызов ядра для получения объекта мьютекса. Для вызова ядра требуются сотни тактов для перехода в режим ядра.
Когда вы успешно получите указатель, внесите изменения в очередь, а затем поменяйте указатель очереди обратно на общий указатель.
Когда вы потребляете элементы из очереди, вы делаете то же самое: поменяйте местами нулевое значение в общем указателе и зацикливайтесь, пока не получите ненулевой результат, оперируйте объектом в локальной переменной, а затем поменяйте его обратно в общую указатель вар.
Эта техника представляет собой комбинацию атомного обмена и коротких циклов вращения. Это хорошо работает в сценариях, где вовлеченные потоки не заблокированы, и столкновения редки. Большую часть времени подкачка будет давать вам эксклюзивный доступ к общему объекту с первой попытки, и, поскольку длительность времени, в течение которого объект очереди удерживается исключительно каким-либо потоком, очень мала, ни один поток не должен будет зацикливаться больше, чем несколько раз, прежде чем объект очереди снова станет доступным.
Если вы ожидаете много конфликтов между потоками в своем сценарии или хотите, чтобы потоки блокировали большую часть своего времени в ожидании выполнения работы, вам может быть лучше обслуживать формальный объект синхронизации мьютекса.