Начиная с версии matplotlib версии 2.1, вы можете использовать легенду фигуры. Вместо ax.legend()
, который создает легенду с ручками из осей ax
, можно создать легенду фигуры
fig.legend(loc=1)
, которая соберет все ручки из всех подзаговоров на рисунке. Поскольку это легенда фигуры, она будет помещена в угол фигуры, а аргумент loc
будет относиться к фигуре.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10)
y = np.linspace(0,10)
z = np.sin(x/3)**2*98
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y, '-', label = 'Quantity 1')
ax2 = ax.twinx()
ax2.plot(x,z, '-r', label = 'Quantity 2')
fig.legend(loc=1)
ax.set_xlabel("x [units]")
ax.set_ylabel(r"Quantity 1")
ax2.set_ylabel(r"Quantity 2")
plt.show()
Чтобы вернуть легенду в оси, вы должны поставить bbox_to_anchor
и bbox_transform
. Последнее было бы преобразованием осей осей, в которых должна находиться легенда. Первые могут быть координатами ребра, определяемого loc
, заданного в координатах осей.
fig.legend(loc=1, bbox_to_anchor=(1,1), bbox_transform=ax.transAxes)
Они НЕ то же самое. Они используются в различных целях!
, В то время как оба типа семафоров имеют полное/пустое состояние и используют тот же API, их использование очень отличается.
Семафоры Взаимного исключения
семафоры Взаимного исключения используются для защиты совместно используемых ресурсов (структура данных, файл, и т.д.).
Взаимоисключающий семафор А "принадлежит" задаче, которая берет его. Если Задача B будет делать попытку к semGive взаимного исключения, в настоящее время сохраненного Задачей A, то вызов B Задачи возвратит ошибку и сбой.
Взаимные исключения всегда используют следующую последовательность:
- SemTake - Critical Section - SemGive
Вот простой пример:
Thread A Thread B Take Mutex access data ... Take Mutex <== Will block ... Give Mutex access data <== Unblocks ... Give Mutex
Двоичный Семафор
Двоичный Семафор обращаются к полностью различному вопросу:
Task A Task B
... Take BinSemaphore <== wait for something
Do Something Noteworthy
Give BinSemaphore do something <== unblocks
Примечание, что с двоичным семафором, для B нормально брать семафор и для предоставления его.
Снова, двоичный семафор НЕ защищает ресурс от доступа. Действие Предоставления и Взятия семафора существенно разъединяется.
Это обычно имеет мало смысла для той же задачи к так даванию и взятию на том же двоичном семафоре.
Ответ может зависеть от целевой ОС. Например, по крайней мере одна реализация RTOS, с которой я знаком, позволит, несколько последовательные "получают" операции против единственного взаимного исключения ОС, пока они - все из того же контекста потока. Несколько добираются, должен быть заменен равным количеством, помещает, прежде чем другому потоку позволят получить взаимное исключение. Это отличается от двоичных семафоров, для которого только сингла добираются, позволяется за один раз, независимо от контекстов потока.
идея позади этого типа взаимного исключения состоит в том, что Вы защищаете объект, только позволяя единственному контексту изменить данные за один раз. Даже если поток получает взаимное исключение и затем вызывает функцию, которая далее изменяет объект (и получает/помещает взаимное исключение средства защиты вокруг его собственных операций), операции должны все еще быть безопасными, потому что они все происходят под единственным потоком.
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
, Конечно, при использовании этой функции, необходимо быть уверены, что все доступы в единственном потоке действительно безопасны!
я не уверен, насколько распространенный этот подход, или применяется ли он за пределами систем, с которыми я знаком. Для примера этого вида взаимного исключения посмотрите ThreadX RTOS.
«бинарный семафор» - это обход языка программирования с использованием «семафора», такого как «мьютекс». Очевидно, есть два очень больших различия:
То, как вы называете каждый из них.
Максимальная длина «идентификатора».
Взаимное исключение может быть выпущено только потоком, который получил его, в то время как можно предупредить о семафоре от любого другого потока (или процесс), таким образом, семафоры более подходят для некоторых проблем синхронизации как производитель-потребитель.
В Windows, двоичные семафоры больше похожи на объекты-события, чем взаимные исключения.
Их семантика синхронизации очень отличается:
Как таковой видит взаимное исключение, поскольку маркер передал от задачи до задач и семафора как транспортный красный свет (это сигналы кто-то, что это может продолжиться).
Мьютекс работает над блокированием критической области, но Семафор работает на счету.
В Windows есть два различия между мьютексами и двоичными семафорами:
Мьютекс может быть освобожден только тем потоком, который владеет, то есть потоком, который ранее вызывал функцию Wait (или который вступил во владение при его создании). Семафор может быть освобожден любым потоком.
Поток может повторно вызывать функцию ожидания в мьютексе без блокировки. Однако, если вы дважды вызываете функцию ожидания для двоичного семафора без освобождения промежуточного семафора, поток блокируется.
Хотя мьютекс & amp; Семафоры используются в качестве примитивов синхронизации, между ними существует большая разница. В случае мьютекса, только поток, который заблокировал или получил мьютекс, может разблокировать его. В случае семафора поток, ожидающий семафора, может сигнализироваться другим потоком. Некоторые операционные системы поддерживают использование mutex & amp; семафоры между процессом. Обычно использование создается в общей памяти.
Вы, очевидно, используете мьютекс для блокировки данных в одном потоке, к которым одновременно обращается другой поток. Предположим, что вы только что позвонили lock()
и в процессе доступа к данным. Это означает, что вы не ожидаете, что какой-либо другой поток (или другой экземпляр того же кода потока) получит доступ к тем же данным, заблокированным тем же мьютексом. То есть, если один и тот же код потока исполняется в другом экземпляре потока, попадает в блокировку, тогда lock()
должен блокировать поток управления там. Это относится к потоку, который использует другой код потока, который также обращается к тем же данным и который также заблокирован тем же мьютексом. В этом случае вы все еще находитесь в процессе доступа к данным, и вам может потребоваться, скажем, еще 15 секунд, чтобы достичь разблокировки мьютекса (чтобы другой поток, блокируемый в блокировке мьютекса, разблокировался и позволил элементу управления доступ к данным). Разрешаете ли вы любой ценой позволить еще одному потоку просто разблокировать тот же мьютекс и, в свою очередь, разрешить потоку, который уже ожидает (блокирует) блокировку мьютекса, разблокировать и получить доступ к данным? Надеюсь, вы поняли, что я здесь говорю? В соответствии с согласованным универсальным определением !,
Итак, если вы очень внимательно относитесь к использованию двоичного семафора вместо мьютекса, то вам следует быть очень осторожным в «определении» блокировок и разблокировок. Я имею в виду, что каждый поток управления, который затрагивает каждую блокировку, должен вызывать вызов разблокировки, также не должно быть никакой «первой разблокировки», скорее это должна быть всегда «первая блокировка».
На теоретическом уровне они не отличаются семантически. Можно реализовать взаимное исключение с помощью семафоров или наоборот (см. здесь для примера). На практике реализация отличается, и они предлагают немного отличающиеся услуги.
практическое различие (с точки зрения системных служб, окружающих их), - то, что реализация взаимного исключения нацелена на то, чтобы быть более легким механизмом синхронизации. В оракуле - говорят, взаимные исключения известны как , фиксаторы и семафоры известны, поскольку ожидает .
На самом низком уровне, они используют своего рода атомарное тест и устанавливают механизм. Это читает текущее значение ячейки памяти, вычисляет своего рода условное выражение и выписывает значение в том местоположении в единственной инструкции, которая не может быть прервана . Это означает, что можно получить взаимное исключение и протестировать, чтобы видеть, было ли у кого-либо еще оно перед Вами.
А типичная взаимоисключающая реализация имеет процесс или поток, выполняющий инструкцию теста-и-набора и оценивающий, установило ли что-либо еще взаимное исключение. Ключевой пункт здесь - то, что нет никакого взаимодействия с планировщик , таким образом, мы понятия не имеем (и не заботьтесь), кто установил блокировку. Тогда мы или бросаем наш интервал времени и делаем попытку его снова, когда задача перенесена, или выполнитесь спин-блокировка . Спин-блокировка является алгоритмом как:
Count down from 5000:
i. Execute the test-and-set instruction
ii. If the mutex is clear, we have acquired it in the previous instruction
so we can exit the loop
iii. When we get to zero, give up our time slice.
, Когда мы закончили выполнять наш защищенный код (известный как критический раздел ) мы просто обнуляем взаимоисключающее значение или независимо от того, что означает 'ясный'. Если несколько задач пытаются получить взаимное исключение они следующая задача, которая, оказывается, планируется после того, как взаимное исключение выпущено, получит доступ к ресурсу. Обычно Вы использовали бы взаимные исключения для управления синхронизируемым ресурсом, где эксклюзивный доступ только необходим в течение очень коротких периодов времени, обычно для создания обновления структуры совместно используемых данных.
семафор А является синхронизируемой структурой данных (обычно использующий взаимное исключение), который имеет количество и некоторые обертки системного вызова, которые взаимодействуют с планировщиком в немного большей глубине, чем взаимоисключающие библиотеки были бы. Семафоры увеличены и постепенно уменьшены и привыкли к [1 110] блок задачи, пока что-то еще не готово. См. проблема Производителя/Потребителя для простого примера этого. Семафоры инициализируются к некоторому значению - двоичный семафор является просто особым случаем, где семафор инициализируется к 1. Регистрация на семафор имеет эффект пробуждения ожидающего процесса.
А основной семафорный алгоритм похож:
(somewhere in the program startup)
Initialise the semaphore to its start-up value.
Acquiring a semaphore
i. (synchronised) Attempt to decrement the semaphore value
ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.
Posting a semaphore
i. (synchronised) Increment the semaphore value
ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.
iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.
В случае двоичного семафора основным практическим различием между этими двумя является природа системных служб, окружающих фактическую структуру данных.
РЕДАКТИРОВАНИЕ: Как evan справедливо указал, спин-блокировки замедлят единственную машину процессора. Вы только использовали бы спин-блокировку на многопроцессорном поле, потому что на единственном процессоре процесс, содержащий взаимное исключение, никогда не будет сбрасывать его, в то время как другая задача работает. Спин-блокировки только полезны на многопроцессорных архитектурах.
Mutex: Предположим, что у нас есть критический раздел, который T1 хочет получить к нему доступ, затем он выполняет следующие шаги. T1:
Двоичный семафор: работает на основе сигналов ожидания и сигнала. wait (s) уменьшает значение "s" на единицу, обычно значение "s" инициализируется значением "1", сигнал (ы) увеличивает значение "s" на единицу. если значение "s" равно 1, значит, никто не использует критическую секцию, когда значение равно 0, означает, что критическая секция используется. Предположим, что поток T2 использует критическую секцию, а затем следует следующие шаги. T2:
Основное различие между Mutex и двоичным семафором заключается в Mutext, если поток блокирует критическую секцию, то он должен разблокировать критическую секцию, никакой другой поток не может разблокировать его , но в случае двоичного семафора, если один поток блокирует критическую секцию с помощью функции wait (s), тогда значение s становится «0», и никто не может получить к нему доступ, пока значение «s» не станет 1, но предположим, что какой-то другой поток вызывает сигнал (ы) ) тогда значение "s" становится 1, и это позволяет другой функции использовать критическую секцию. следовательно, в двоичном семафорном потоке нет владения.
Туалетным примером является приятная аналогия:
Взаимное исключение:
ключ к туалету. У одного человека может быть ключ - занимают туалет - в то время. По окончании человек дает (освобождает) ключ к следующему человеку в очереди.
Официально: "Взаимные исключения обычно используются для сериализации доступа к разделу повторно используемого кода, который не может быть выполнен одновременно больше чем одним потоком. Взаимоисключающий объект только позволяет один поток в управляемый раздел, вызывая другие потоки, которые пытаются получить доступ к тому разделу для ожидания, пока первый поток не вышел от того раздела". Касательно: Библиотека Разработчика Symbian
(Взаимное исключение является действительно семафором со значением 1.)
Семафор:
количество свободных идентичных туалетных ключей. Пример, говорят, что у нас есть четыре туалета с идентичными блокировками и ключи. Семафорное количество - количество ключей - установлено на 4 вначале (все четыре туалета свободны), тогда значение количества постепенно уменьшается, поскольку люди входят. Если все туалеты полны, т.е. нет никаких свободных оставленных ключей, семафорное количество 0. Теперь, когда eq., один человек покидает туалет, семафор, увеличен до 1 (один свободный ключ) и дан следующему человеку в очереди.
Официально: "Семафор ограничивает число одновременных пользователей совместно используемого ресурса до максимального количества. Потоки могут запросить доступ к ресурсу (постепенно уменьшающий семафор) и могут сигнализировать, что они закончили использовать ресурс (увеличивающий семафор)". Касательно: Библиотека Разработчика Symbian
Важным вопросом является параллелизм. Существует больше чем один поток управления. Думайте приблизительно два процесса с помощью общей памяти. Теперь только один процесс может получить доступ к общей памяти за один раз. Если бы больше чем один процесс получает доступ к общей памяти за один раз, содержание общей памяти повредить. Это похоже на железнодорожный путь. Только один поезд может работать на нем, еще был бы несчастный случай. Таким образом, существует сигнальный механизм, который проверяет драйвер. Если сигнал является зеленым, поезд может пойти и если это красно, он должен ожидать для использования дорожки. Так же в случае общей памяти, существует двоичный семафор. Если семафор равняется 1, процесс получает его (делает его 0), и идет вперед и получает доступ к нему. Если семафор 0, процесс ожидает. Функциональность, которую должен обеспечить двоичный семафор, является взаимным исключением (или взаимное исключение, короче говоря) так, чтобы только один из многих параллельных объектов (процесс или поток) взаимно исключил других. Это плюс это, у нас есть семафоры подсчета, которые помогают в синхронизации нескольких экземпляров ресурса.
Взаимное исключение является основной функциональностью, обеспеченной семафорами. Теперь в контексте потоков, у нас могли бы быть другое имя и синтаксис для него. Но базовое понятие является тем же: как сохранить целостность кода и данных в параллельном программировании. По-моему, вещами как владение и связанными проверками являются улучшения, обеспеченные реализациями.
Nice articles on the topic:
From part 2:
The mutex is similar to the principles of the binary semaphore with one significant difference: the principle of ownership. Ownership is the simple concept that when a task locks (acquires) a mutex only it can unlock (release) it. If a task tries to unlock a mutex it hasn’t locked (thus doesn’t own) then an error condition is encountered and, most importantly, the mutex is not unlocked. If the mutual exclusion object doesn't have ownership then, irrelevant of what it is called, it is not a mutex.
Модифицированный вопрос - В чем разница между мьютексом и "бинарным" семафором в "Linux"?
Ответ: Ниже приведены различия... i) Область применения - Область применения мьютекса находится в пределах адресного пространства процесса, который его создал, и используется для синхронизации потоков. В то время как семафор может использоваться в пространстве процессов и, следовательно, может использоваться для межпроцессной синхронизации.
ii) Mutex легче и быстрее семафора. Futex еще быстрее.
iii) Мьютекс может быть успешно приобретен одним и тем же потоком несколько раз с условием, что он должен освободить его столько же раз. Другой поток, пытающийся приобрести мутекс, будет блокирован. В то время как в случае с семафором, если тот же процесс попытается приобрести его снова, он заблокируется, так как его можно приобрести только один раз.
Помимо того, что у мьютексов есть владелец, два объекта могут быть оптимизированы для различного использования. Мьютексы предназначены для кратковременного удержания; нарушение этого правила может привести к снижению производительности и несправедливому планированию. Например, запущенному потоку может быть разрешено получить мьютекс, даже если другой поток уже заблокирован на нем. Семафоры могут обеспечить большую справедливость, или же справедливость может быть принудительной с использованием нескольких условных переменных.
Лучшее решение
единственная разница
1. Взаимное исключение-> блокирует и разблокировало, находятся в собственности потока, который блокирует взаимное исключение.
2. Семафор-> Никакое владение т.е.; если один поток называет semwait (s), любой другой поток может назвать sempost (s) для удаления блокировки.