Я обнаружил, что %matplotlib notebook
работает лучше для меня, чем встроенный с ноутбуками Jupyter.
Обратите внимание, что вам, возможно, потребуется перезапустить ядро, если раньше вы использовали %matplotlib inline
.
доступ через 'Экземпляр' к 'Переключателю ()' ориентированный на многопотоковое исполнение класс? Если да, какой предположения, правила, и т.д. Если не, почему и как я могу зафиксировать его?
нет, это не ориентировано на многопотоковое исполнение.
В основном, оба потока могут работать эти Toggle
функция одновременно, таким образом, это могло произойти
// thread 1 is running this code
if(value == 0)
{
value = 1;
// RIGHT NOW, thread 2 steps in.
// It sees value as 1, so runs the other branch, and changes it to 0
// This causes your method to return 0 even though you actually want 1
}
else if(value == 1)
{
value = 0;
}
return value;
, необходимо действовать со следующим предположением.
, Если 2 потока работают, они могут и чередоваться и взаимодействовать друг с другом случайным образом в любой точке. Можно быть половиной пути посредством записи или чтения целого числа на 64 бита или плавания (на ЦП на 32 бита), и другой поток может вскочить и изменить его из нижней части Вы.
, Если 2 потока никогда не получают доступ ни к чему общему, это не имеет значения, но как только они делают, необходимо препятствовать тому, чтобы они ступили на каждого пальцы ног других. Способ сделать это в.NET с блокировками.
можно решить, какой и где заблокировать путем размышления о вещах как это:
Для данного блока кода, если бы значение something
было изменено из нижней части меня, это имело бы значение? Если бы это было бы, то необходимо заблокировать это something
на время кода, где это имело бы значение.
Рассмотрение Вашего примера снова
// we read value here
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
// and we return it here
return value;
Для этого для возврата, к чему мы ожидаем это мы предполагаем, что value
не будет изменен между чтением и return
. Для этого предположения, чтобы на самом деле быть корректными, необходимо заблокировать value
на время того блока кода.
, Таким образом, Вы сделали бы это:
lock( value )
{
if(value == 0)
... // all your code here
return value;
}
ОДНАКО
В.NET можно только заблокировать Ссылочные типы. Int32 является Типом Значения, таким образом, мы не можем заблокировать его.
Мы решаем это путем представления 'фиктивного' объекта и блокировки , что везде, где мы хотели бы заблокировать 'значение'.
Это - то, к чему обращается Ben Scheirman .
Исходная реализация не ориентирована на многопотоковое исполнение, как Ben указывает
А простой способ сделать, это ориентированный на многопотоковое исполнение должно представить оператор блокировки. Например, как это:
public class MyClass
{
private Object thisLock = new Object();
private static readonly MyClass instance = new MyClass();
public static MyClass Instance
{
get { return instance; }
}
private Int32 value = 0;
public Int32 Toggle()
{
lock(thisLock)
{
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
return value;
}
}
}
Ваш поток мог остановиться посреди того метода и передать управление другому потоку. Вам нужен критический раздел вокруг того кода...
private static object _lockDummy = new object();
...
lock(_lockDummy)
{
//do stuff
}
Я также добавил бы защищенного конструктора к MyClass, чтобы препятствовать тому, чтобы компилятор генерировал общедоступного конструктора по умолчанию.
я думал, что, если бы я вывожу шаблон "одиночка" и вынуждаю всех получить новый экземпляр класса, он упростил бы некоторые проблемы..., но это не мешает никому больше инициализировать статический объект того типа и раздать это... или от отделения нескольких потоков, всего доступа 'Переключатель ()' от того же экземпляра.
Бинго :-)
я получаю его теперь. Это - жесткий мир. Мне жаль, что я не осуществлял рефакторинг унаследованный код :(
, К сожалению, многопоточность трудна, и необходимо быть очень параноиками о вещах :-) Простое решение в этом случае состоит в том, чтобы придерживаться одиночного элемента и добавить блокировку вокруг значения, как в примерах.
, Именно это я думал. Но, я я ищу детали... 'Переключитесь ()', не статический метод, но это - член статического свойства (при использовании 'Экземпляра'). Это то, что делает это общими для потоками?
, Если Ваше приложение является многопоточным и можно предвидеть, что несколько распараллеливают, получит доступ к тому методу, который делает его общими для потоками. Поскольку Ваш класс является Singleton, Вы знаете, что другой поток получит доступ к ТОМУ ЖЕ объекту, так предостережется о потокобезопасности Ваших методов.
И как это относится к одиночным элементам в целом. Я должен был бы обратиться к этому в каждом методе на моем классе?
, Поскольку я сказал выше, потому что это - одиночный элемент, Вы знаете, что другой поток получит доступ к тому же объекту, возможно одновременно. Это не означает, что необходимо заставить каждый метод получить блокировку. Если Вы замечаете, что simultaneos вызов может привести к поврежденному состоянию класса, то необходимо применить метод, упомянутый @Thomas
я могу предположить, что шаблон "одиночка" подвергает мой в других отношениях прекрасный ориентированный на многопотоковое исполнение класс всем проблемам потока постоянных статических участников?
номер Ваш класс просто не ориентирован на многопотоковое исполнение. Одиночный элемент не имеет никакого отношения к нему.
(я получаю голову вокруг того, что члены экземпляра обратились к статическому объекту, вызывают проблемы многопоточности)
, Она не имеет отношения к этому также.
необходимо думать как это: для 2 (или больше) потоки действительно ли возможно в моей программе получить доступ к этой части данных одновременно?
то, что Вы получаете данные через одиночный элемент или статическую переменную, или передающий в объекте как параметр метода, не имеет значения. В конце дня это - все просто некоторые биты и байты в RAM Вашего ПК и всем, что имеет значение, видят ли несколько потоков те же биты.
Кавычка:
if(value == 0) { value = 1; }
if(value == 1) { value = 0; }
return value;
value
всегда будет 0...
Ну, я на самом деле не знаю C#, что хорошо..., но я в порядке в Java, таким образом, я дам ответ для этого, и надо надеяться эти два достаточно подобны, что это будет полезно. В противном случае я приношу извинения.
ответ, нет, это не безопасно. Один поток мог назвать Переключатель () в то же время, что и другой, и это возможно, хотя вряд ли с этим кодом, это Thread1 мог установить value
промежуточный времена, что Thread2 проверяет его и когда он устанавливает его.
Для фиксации просто сделайте Переключатель () synchronized
. Это не блокируется ни на чем или называет что-либо, что могло бы породить другой поток, который мог назвать Переключатель (), таким образом, это - все, что необходимо сделать, сохраняют его.