Здравствуйте, Аноним, Вы писали:
А>Есть метод DoSomething в котором происходит асинхронный запрос к БД для работы с объектом имеющего уникальный ID, нужно чтобы пока обрабатывается объект новый асинхронный запрос не прошел.
А>[c#]
Как то странно получается: "Синхронный запрос через асинхронные методы" В чём фишка?
Здравствуйте, Аноним, Вы писали:
А>Возможно для этих целей лучше использовать какие-то объекты синхронизации ( мутекс и т.п. ).
Для этих целей можно взять ReaderWriterLock. Dictionary потокобезопасна для чтения.
A Dictionary(Of TKey, TValue) can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, GlebZ, Вы писали:
GZ>Вероятнее всего можно, но так не принято. Объект может локироваться самим объектом, либо другим чужим или полузабытым кодом. Что может привести к дедлокам. Поэтому принято локировать явно через свои object.
Это кем так принятно? Если мне память не изменяет, в гайдлайнах наоборот написано, чтобы сами классы не лочились на this — именно потому, что на них может лочиться внешний код. Вы не предлагаете просто плодить сущности (помимо комплекта полей-данных иметь параллельный комплект полей-"локеров" и не забывать всё это поддерживать тоже параллельно)...
_FR>In general, avoid locking on a public type, or instances beyond your code's control.
_FR>…
_FR>Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
Насколько я понял, это относится к дизайну библиотек (потому что у "конечного" кода не может быть "instances beyond your code's control"). Соответственно не рекомендуют лочиться в библиотеках именно потому, что вызывающий код может (и будет) лочиться на них. Не зря же упомянули только публичные типы
Strictly speaking, the object provided is used solely to uniquely identify the resource being shared among multiple threads, so it can be an arbitrary class instance. In practice, however, this object usually represents the resource for which thread synchronization is necessary. For example, if a container object is to be used by multiple threads, then the container can be passed to lock, and the synchronized code block following the lock would access the container. As long as other threads locks on the same contain before accessing it, then access to the object is safely synchronized.
Strictly speaking, the object provided is used solely to uniquely identify the resource being shared among multiple threads, so it can be an arbitrary class instance. In practice, however, this object usually represents the resource for which thread synchronization is necessary. For example, if a container object is to be used by multiple threads, then the container can be passed to lock, and the synchronized code block following the lock would access the container. As long as other threads locks on the same contain before accessing it, then access to the object is safely synchronized.
В документации к goto приведено несколько сценариев его использования, но, подходя к програмированию разумно, не все их следует использовать, тем более, повсеместно. Так же и здесь: если дана ссылку на какую-то цитату, это вовсе не означает, что всё произведение в целом есть истина.
В МСДН есть не мало очень умных мыслей. А есть и просто вредные.
В примере в статье, на которую вы ссылаетесь (как, кажется, и везде в МСДН), lockThis даже без ридлонли объявлен — что конечно же никак не влият на _работоспособность_ кода, но может оказаться весьма важным при использовании/поддержке/рефакторинге/переписывании.
Например, в данной статье никак не сказано, как процитированный кусок сочитается с SRP, однако весьма разумно держать это у себя в голове постоянно, и экземпляры объектов (" container object") использовать для одних целей (для которых они напрямую предназначены), а для синхронизации использовать нечто другое, самостоятельное.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Чем потокобезопастность нашего кода, в случае использования специального объекта синхронизации будет отличаться? А то, что SRP нарушается видно очень хорошо: при необходимости реализации другого сценария потокобезопастности может потребоваться синхронизироваться по другому объекту. Если одна синхронизация делается на самом неком объекте, а другая — на объекте сбоку, то возникает вопрос — почему по сути одно и то же реализовано по-разному?
SRP не про то, что нельзя один и тот же класс использовать для разных целей, он про то, что конкретный экземпляр класса нужно использовать для одной цели. Если определить цель как "потокобезопасная коллекция", то всё встаёт на свои места.
Вообще же в реальности я обычно в таком случае использую потокобезопасные агрегаты коллекций, которые обеспечивают потокобезопасность внутри себя, позволяя освободить внешний код то мусора, вызванного необходимостью синхронизации.
Здравствуйте, koandrew, Вы писали:
K>Здравствуйте, Константин Л., Вы писали:
КЛ>>лочась на объект, для этого не предназначенный, ты повышаешь энтропию. объекты синхронизации это не лишние сущности. я предпочитаю заводить readonly object и спать спокойно.
K>Любой объект предназначен для лока.
случайность и сахар. я бы его убрал, кстати
K>Энтропия системы остаётся постоянно.
ну уж нет
K>А вот добавляя объекты-локеры, ты как раз повышаешь энтропию, ко всему прочему ещё и заставляя поддерживающих твой код быть в курсе того, что для K>безопасного доступа к объекту Х надо лочиться на объекте Y.
да, еще имена переменным обычно дают отличные от apsidlasjdhjy. черт,, это все вообще не проблема
K>Эти объекты никак не связаны друг с другом, а посему саппортерами нужно будет разбираться во всём коде, чтобы увидеть эту связь.
да, в таком коде нужно разбираться неделями (псевдокод):
readonly HashSet<long> InProgress = new HashSet<long>();
readonly object InProgressSync = new object();
bool SetInProgress(long id)
{
lock (InProgressSync)
{
if (InProgress.Contains(id))
return false;
InProgress.Add(id);
return true;
}
}
с чем тут надо разбираться?
K>В то время как знание о том, что для обеспечения синхронизированного доступа к объекту нужно на нём залочиться, даётся MSDN'ом и всеми K>книжками по языку и библиотеке, так что мы вправе принять наличие этого знания как данность.
частный случай. обычно лочат код, а не объекты. лочить объекты дурной тон. лочить нужно код
Как сделать потокобезопасный Dictionary
От:
Аноним
Дата:
19.10.10 18:03
Оценка:
Есть метод DoSomething в котором происходит асинхронный запрос к БД для работы с объектом имеющего уникальный ID, нужно чтобы пока обрабатывается объект новый асинхронный запрос не прошел.
public static void DoSomething( int ID )
{
/// Здесь асинхронный вызов некой хранимки с передачей ей ID,
}
public static void DoSomethingFinished( .. )
{
/// Здесь получаем результаты асинхронного запроса
}
т.е. нужно немного доработать , примерно так
private static Dictionary<int, bool> m_InProc;
public static void DoSomething( int ID )
{
if ( m_InProc.ContainKey( ID ) )
{
if ( m_InProc[ID] )
return;
}
m_InProc[ID] = true;
/// Здесь асинхронный вызов некой хранимки с передачей ей ID,
}
public static void DoSomethingFinished( .. )
{
/// Здесь получаем результаты асинхронного запроса
m_InProc[ID] = false;
}
Возможно для этих целей лучше использовать какие-то объекты синхронизации ( мутекс и т.п. ).
Re[2]: Как сделать потокобезопасный Dictionary
От:
Аноним
Дата:
19.10.10 18:40
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Есть метод DoSomething в котором происходит асинхронный запрос к БД для работы с объектом имеющего уникальный ID, нужно чтобы пока обрабатывается объект новый асинхронный запрос не прошел.
А>>[c#]
А>Как то странно получается: "Синхронный запрос через асинхронные методы" В чём фишка?
Нет это не синхронный запрос, если заметили то там просто return.
То есть если 2 потока пихнут на обработку одинаковый ID, например =1 , то пока первый обрабатывается второй будет игнорироваться, процедура не "зависает" как при синхронном запросе , а просто игнорирует дублирующий запрос.
При этом 2й поток может послать DoSomething(2) и DoSomething(3) которые будут работать паралельно с DoSomething(1)
Или один поток может вызвать DoSomething(1) и через некоторое время послать DoSomething(2), DoSomething(3) и еще раз DoSomething(1) , а первый запрос еще может не завершится.
Я не профессионал многопоточности, но возможно, можно сделать так.
Создать объект для блокировки:
private static object dictionaryLock = new object();
Обернуть все обращения к dictionary конструкцией lock (dictionaryLock) {...}.
Таким образом вы сделаете работу с dictionary потокобезопасной. Остальная часть кода (длительно выполняющаяся) будет запускаться однократно для каждого ID только после потокобезопасной проверки словаря.
Re[4]: Как сделать потокобезопасный Dictionary
От:
Аноним
Дата:
20.10.10 04:01
Оценка:
Здравствуйте, victor_kr, Вы писали:
_>Я не профессионал многопоточности, но возможно, можно сделать так.
_>Создать объект для блокировки:
_>private static object dictionaryLock = new object();
_>Обернуть все обращения к dictionary конструкцией lock (dictionaryLock) {...}.
_>Таким образом вы сделаете работу с dictionary потокобезопасной. Остальная часть кода (длительно выполняющаяся) будет запускаться однократно для каждого ID только после потокобезопасной проверки словаря.
Интересно, а у object вроде бы нет свойств типа "сигнальное состояние". Соотвественно lock( myobject ) наверное управляет состоянием посредством ссылки на object , а сам object при этом не затрагивается . Почему бы в таком случае не лочить сразу статический объект Dictionary , т.е.
lock( myDictionary )
{
/// работа с myDictionary.
}
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, victor_kr, Вы писали:
_>>Я не профессионал многопоточности, но возможно, можно сделать так.
_>>Создать объект для блокировки:
_>>private static object dictionaryLock = new object();
_>>Обернуть все обращения к dictionary конструкцией lock (dictionaryLock) {...}.
_>>Таким образом вы сделаете работу с dictionary потокобезопасной. Остальная часть кода (длительно выполняющаяся) будет запускаться однократно для каждого ID только после потокобезопасной проверки словаря.
А>Интересно, а у object вроде бы нет свойств типа "сигнальное состояние". Соотвественно lock( myobject ) наверное управляет состоянием посредством ссылки на object , а сам object при этом не затрагивается . Почему бы в таком случае не лочить сразу статический объект Dictionary , т.е. А>
А>lock( myDictionary )
А>{
А> /// работа с myDictionary.
А>}
А>
Можно и так, использование отдельного объекта для синхронизации позволяет лучше видеть что мы делаем. К тому же если нам надо будет
синхронизировать доступ сразу к нескольким полям удобней это будет делать через выделенный объект для синхронизации, что бы не писать такое:
lock(var_1){
lock(var_2){
//здесь потокобезопасный
//доступ к var_1 и var_2
}
}
Вероятнее всего можно, но так не принято. Объект может локироваться самим объектом, либо другим чужим или полузабытым кодом. Что может привести к дедлокам. Поэтому принято локировать явно через свои object.
Здравствуйте, Аноним, Вы писали:
А>Интересно, а у object вроде бы нет свойств типа "сигнальное состояние". Соотвественно lock( myobject ) наверное управляет состоянием посредством ссылки на object , а сам object при этом не затрагивается . Почему бы в таком случае не лочить сразу статический объект Dictionary
Потому что очень бывает полезно читать, хотя бы документацию:
In general, avoid locking on a public type, or instances beyond your code's control.
…
Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lloyd, Вы писали:
L>Посмотрите ReaderWriterLockSlim. Там в примерах как раз рассмотрен ваш случай.
У Joe Duffy в блогах было неплохое сравнение реализаций разных ReaderWriter'ов, критической секции и спинлоков. Вывод довольно забавный: readerwriter'ы в случае частой записи прилично сливают обычным критическим секциям и спинлокам.
А сам словарь требует защиты? То есть возможно-ли добавление-удаление в него элементов из разных потоков, или, допустим одновременно с вызовом DoSomething или DoSomethingFinished? Если нет, синхронизировать доступ к словарю нет смысла.
Если есть возможность расширить хранящиеся объекты, то можно добавить им методы Acquire-Release. Если возможности нет, можно создать контейнер для хранения их в словаре, типа
private class DictItem<T>
{
private int _locked;
public bool Acquire(){return 0 == Interlocked.Exchenge(ref _locked, 1);}
public void Release(){Interlocked.Exchenge(ref _locked, 0);}
public T Item;
}
Можно конечно хранить состояние в отдельном массиве, но лично мне это не нравится. Признаться, мне эта ситуация вообще не нравится, боюсь, в будущем она может создать немало проблем, но Вам на месте должно быть виднее.
_FR>>In general, avoid locking on a public type, or instances beyond your code's control.
_FR>>…
_FR>>Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
K>Насколько я понял, это относится к дизайну библиотек (потому что у "конечного" кода не может быть "instances beyond your code's control").
Я почему-то не знаю, что такое "конечный код" и чем он отличается от какого-то другого кода.
K>Соответственно не рекомендуют лочиться в библиотеках именно потому, что вызывающий код может (и будет) лочиться на них. Не зря же упомянули только публичные типы
Почему слово public обязательно следует понимать буквально? Ничто не мешает понимать его как видимое где-то снаружи.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, koandrew, Вы писали:
K>Здравствуйте, GlebZ, Вы писали:
GZ>>Вероятнее всего можно, но так не принято. Объект может локироваться самим объектом, либо другим чужим или полузабытым кодом. Что может привести к дедлокам. Поэтому принято локировать явно через свои object.
K>Это кем так принятно? Если мне память не изменяет, в гайдлайнах наоборот написано, чтобы сами классы не лочились на this — именно потому, что на них может лочиться внешний код. Вы не предлагаете просто плодить сущности (помимо комплекта полей-данных иметь параллельный комплект полей-"локеров" и не забывать всё это поддерживать тоже параллельно)...
1. многими
2. это не "плодить сущности", это писать безопасный код
Здравствуйте, koandrew, Вы писали:
K>Здравствуйте, _FRED_, Вы писали:
_FR>>
_FR>>In general, avoid locking on a public type, or instances beyond your code's control.
_FR>>…
_FR>>Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
K>Насколько я понял, это относится к дизайну библиотек (потому что у "конечного" кода не может быть "instances beyond your code's control"). Соответственно не рекомендуют лочиться в библиотеках именно потому, что вызывающий код может (и будет) лочиться на них. Не зря же упомянули только публичные типы
Объекты бизнес-логики не стоит использовать для блокировок, так как у них есть свое назначение. Эти объекты могут удаляться/изменяться/пересоздаваться. Объект блокировки создается для того чтобы решать одну задачу — блокировка доступа. Таким образом можно разделить ответственность и избежать проблем. При использовании отдельных блокирующих объектов не нужно помнить о том, что нельзя пересоздать объект бизнес-логики потому что он где-то используется в качестве блокировки.
Здравствуйте, _FRED_, Вы писали:
_FR>В документации к goto приведено несколько сценариев его использования, но, подходя к програмированию разумно, не все их следует использовать, тем более, повсеместно. Так же и здесь: если дана ссылку на какую-то цитату, это вовсе не означает, что всё произведение в целом есть истина.
_FR>В МСДН есть не мало очень умных мыслей. А есть и просто вредные.
_FR>В примере в статье, на которую вы ссылаетесь (как, кажется, и везде в МСДН), lockThis даже без ридлонли объявлен — что конечно же никак не влият на _работоспособность_ кода, но может оказаться весьма важным при использовании/поддержке/рефакторинге/переписывании.
Всё вышесказанное не имеет отношения к обсуждаемой теме.
_FR>Например, в данной статье никак не сказано, как процитированный кусок сочитается с SRP, однако весьма разумно держать это у себя в голове постоянно, и экземпляры объектов (" container object") использовать для одних целей (для которых они напрямую предназначены), а для синхронизации использовать нечто другое, самостоятельное.
SRP тут не нарушается, потому что тот факт, что мы на нём лочимся, никак не меняет его функционал — просто делает _наш код_ потокобезопасным.
Здравствуйте, _FRED_, Вы писали:
_FR>Почему слово public обязательно следует понимать буквально? Ничто не мешает понимать его как видимое где-то снаружи.
А что кроме public является "видимым где-то снаружи"? Снаружи чего кстати?
Здравствуйте, koandrew, Вы писали:
_FR>>В документации к goto приведено несколько сценариев его использования, но, подходя к програмированию разумно, не все их следует использовать, тем более, повсеместно. Так же и здесь: если дана ссылку на какую-то цитату, это вовсе не означает, что всё произведение в целом есть истина. _FR>>В МСДН есть не мало очень умных мыслей. А есть и просто вредные. _FR>>В примере в статье, на которую вы ссылаетесь (как, кажется, и везде в МСДН), lockThis даже без ридлонли объявлен — что конечно же никак не влият на _работоспособность_ кода, но может оказаться весьма важным при использовании/поддержке/рефакторинге/переписывании. K>Всё вышесказанное не имеет отношения к обсуждаемой теме.
Имеет Я же в ответ на свою цитату получил другую без какого-то бы нибыло разъяснения.
_FR>>Например, в данной статье никак не сказано, как процитированный кусок сочитается с SRP, однако весьма разумно держать это у себя в голове постоянно, и экземпляры объектов (" container object") использовать для одних целей (для которых они напрямую предназначены), а для синхронизации использовать нечто другое, самостоятельное. K>SRP тут не нарушается, потому что тот факт, что мы на нём лочимся, никак не меняет его функционал — просто делает _наш код_ потокобезопасным.
Чем потокобезопастность нашего кода, в случае использования специального объекта синхронизации будет отличаться? А то, что SRP нарушается видно очень хорошо: при необходимости реализации другого сценария потокобезопастности может потребоваться синхронизироваться по другому объекту. Если одна синхронизация делается на самом неком объекте, а другая — на объекте сбоку, то возникает вопрос — почему по сути одно и то же реализовано по-разному?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, koandrew, Вы писали:
K>Здравствуйте, Константин Л., Вы писали:
КЛ>>1. многими КЛ>>2. это не "плодить сущности", это писать безопасный код
K>Аргументация?
лочась на объект, для этого не предназначенный, ты повышаешь энтропию. объекты синхронизации это не лишние сущности. я предпочитаю заводить readonly object и спать спокойно.
Здравствуйте, koandrew, Вы писали:
_FR>>Почему слово public обязательно следует понимать буквально? Ничто не мешает понимать его как видимое где-то снаружи.
K>А что кроме public является "видимым где-то снаружи"?
Как минимум, то, что называется internal.
K>Снаружи чего кстати?
Снаружи — означает "извне". Чего именно — да чего угодно, никаких не соответствий не вижу.
Например, снаружи вложенного private-класса видны его public-члены, но более "снаружи" уже нет. Попадают ли такие public-члены под термин "public", используемый в гайдлайнах? Чаще всего, нет. Но в некоторой узкой и очень близкой области эпсилон эта непубличность может быть очень даже заметна. Поэтому под "public" в цитате не следует понимать все открытые члены открытых типов, видимые в сторонних сборках. А именно это и подразумевается в MSDN.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, koandrew, Вы писали:
_FR>>>Почему слово public обязательно следует понимать буквально? Ничто не мешает понимать его как видимое где-то снаружи.
K>>А что кроме public является "видимым где-то снаружи"?
_FR>Как минимум, то, что называется internal.
K>>Снаружи чего кстати?
_FR>Снаружи — означает "извне". Чего именно — да чего угодно, никаких не соответствий не вижу.
_FR>Например, снаружи вложенного private-класса видны его public-члены, но более "снаружи" уже нет. Попадают ли такие public-члены под термин "public", используемый в гайдлайнах? Чаще всего, нет. Но в некоторой узкой и очень близкой области эпсилон эта непубличность может быть очень даже заметна. Поэтому под "public" в цитате не следует понимать все открытые члены открытых типов, видимые в сторонних сборках. А именно это и подразумевается в MSDN.
+1
я вообще не понимаю какой смысл писать многопоточный код по-разному в зависимости от того, публичный он или нет? писать надо всегда максимально безопасно вне зависимости от purposes.
Здравствуйте, Константин Л., Вы писали:
КЛ>лочась на объект, для этого не предназначенный, ты повышаешь энтропию. объекты синхронизации это не лишние сущности. я предпочитаю заводить readonly object и спать спокойно.
Любой объект предназначен для лока. Энтропия системы остаётся постоянно. А вот добавляя объекты-локеры, ты как раз повышаешь энтропию, ко всему прочему ещё и заставляя поддерживающих твой код быть в курсе того, что для безопасного доступа к объекту Х надо лочиться на объекте Y. Эти объекты никак не связаны друг с другом, а посему саппортерами нужно будет разбираться во всём коде, чтобы увидеть эту связь. В то время как знание о том, что для обеспечения синхронизированного доступа к объекту нужно на нём залочиться, даётся MSDN'ом и всеми книжками по языку и библиотеке, так что мы вправе принять наличие этого знания как данность.
Здравствуйте, _FRED_, Вы писали:
K>>А что кроме public является "видимым где-то снаружи"?
_FR>Как минимум, то, что называется internal.
K>>Снаружи чего кстати?
_FR>Снаружи — означает "извне". Чего именно — да чего угодно, никаких не соответствий не вижу.
_FR>Например, снаружи вложенного private-класса видны его public-члены, но более "снаружи" уже нет. Попадают ли такие public-члены под термин "public", используемый в гайдлайнах? Чаще всего, нет. Но в некоторой узкой и очень близкой области эпсилон эта непубличность может быть очень даже заметна. Поэтому под "public" в цитате не следует понимать все открытые члены открытых типов, видимые в сторонних сборках. А именно это и подразумевается в MSDN.
Под "публичностью" в процитированной мною (да и тобой) статье подразумевается "доступность из кода, который использует ваш класс и при этом неподконтролен вам". По-моему достаточно чёткое определение, и под него чаще всего попадают именно public-члены.
Здравствуйте, koandrew, Вы писали:
_FR>>Чем потокобезопастность нашего кода, в случае использования специального объекта синхронизации будет отличаться? А то, что SRP нарушается видно очень хорошо: при необходимости реализации другого сценария потокобезопастности может потребоваться синхронизироваться по другому объекту. Если одна синхронизация делается на самом неком объекте, а другая — на объекте сбоку, то возникает вопрос — почему по сути одно и то же реализовано по-разному?
K>SRP не про то, что нельзя один и тот же класс использовать для разных целей, он про то, что конкретный экземпляр класса нужно использовать для одной цели. Если определить цель как "потокобезопасная коллекция", то всё встаёт на свои места.
Если говорить такой о задаче класса, как "потокобезопастная коллекция", то использование lock(внутреннее хранилище) — это отвратительный дизайн. Кстати, очень хороший пример, что бы объяснить почему.
Итак, у нас есть задача сделать потокобезопастную коллекцию.
В обсуждаемом вопросе у нас есть два пути: послушаться меня и завести отдельно поле для синхронизации и послушаться чего-то ещё и лочится, не заморачиваясь со специальным полем, на имеющееся поле внутреннего хранилища. Работать два варианта буду одинаково. Прекрасно.
Теперь вспомним, о чём я предупреждал и посмотрим, что в [интерфейсе] нашей коллекции можно улучшить. Казалось бы — ничего? Коллекция она и есть коллекция и со времён первого фреймворка принципиально не менялась? Ан нет. Есть одно отличие, связанное как раз с многопоточностью: из коллекции ушло свойство SyncRoot. Ушло потому, что во многих сценариях требуется извне задать коллекции объект, по которому требуется синхронизировать обращение к внутреннему хранилищу.
Именно из высказанных мной соображений в одном из предыдущих ответов видно, что послушай вы меня, рефактори и изменять сделанную вами коллекцию было бы гораздо проще, достаточно поменять инициализацию поля синхронизации с new object() на присваение некоего пользователького объекта, переданного в конструктор. Пойди вы по предлагаемому вами пути, вам пришлось бы изменить весь код синхронизации. Не сильно, да. Но весь.
Далее, можем добавить нашей коллекции возможность принимать извне не только объект синхронизации, но и хранилище, в которое синхронно будут записываться данные. Синхронизироваться по такому, переданному извне объекту так же уже не хорошо.
Так вот моё предложение как раз способствует написанию такого кода, который будет дешевле всего поддерживать, потому что в нём нет вынужденных, не обязательных связей между сущностями, ибо каждая такая связь -гвоздь в крышку гроба того, что вы делаете.
K>Вообще же в реальности я обычно в таком случае использую потокобезопасные агрегаты коллекций, которые обеспечивают потокобезопасность внутри себя, позволяя освободить внешний код то мусора, вызванного необходимостью синхронизации.
Что есть агрегат коллекции? Вообще, "потокобезопастная коллекция" сама в себе очень не нужна. Потокобезопастными имеет смысл делать не столько объекты, сколько операции, сценарии работы, более общие, чем "добавить сюда элемент".
Но мы же тут не о подходе, а о способе реализации маленькой частички обеспечения синхронности, которая, однако, используется довольно часто.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, koandrew, Вы писали:
K>>>А что кроме public является "видимым где-то снаружи"? _FR>>Как минимум, то, что называется internal. K>>>Снаружи чего кстати? _FR>>Снаружи — означает "извне". Чего именно — да чего угодно, никаких не соответствий не вижу. _FR>>Например, снаружи вложенного private-класса видны его public-члены, но более "снаружи" уже нет. Попадают ли такие public-члены под термин "public", используемый в гайдлайнах? Чаще всего, нет. Но в некоторой узкой и очень близкой области эпсилон эта непубличность может быть очень даже заметна. Поэтому под "public" в цитате не следует понимать все открытые члены открытых типов, видимые в сторонних сборках. А именно это и подразумевается в MSDN.
K>Под "публичностью" в процитированной мною (да и тобой) статье подразумевается "доступность из кода, который использует ваш класс и при этом неподконтролен вам". По-моему достаточно чёткое определение, и под него чаще всего попадают именно public-члены.
Я опять же не знаю, что такое "неподконтролен вам". И почему это "подконтрольный мне" код должен делать более предлоложений о работе некоего кода Х чем другой код?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, koandrew, Вы писали:
K>SRP не про то, что нельзя один и тот же класс использовать для разных целей, он про то, что конкретный экземпляр класса нужно использовать для одной цели.
Неверное опеределение. Классы могут быть классами-состояния, и классами-поведения. Лочат собственно доступ к ресурсу или набору ресурсов, то есть классу состояния. А он уже используется для разных целей. Поэтому решение как лочить должно лежать на объектах бизнес-логики.
K>Если определить цель как "потокобезопасная коллекция", то всё встаёт на свои места.
Две "потокобезопасных коллекции" уже не являются "потокобезопасными". Сама коллекция может быть потокобезопасна только при атомарных операциях.
Здравствуйте, _FRED_, Вы писали:
_FR>Я опять же не знаю, что такое "неподконтролен вам". "Неподконтрольный вам" == "написанный и поддерживаемый не вами (не вашим тимом/компанией)". _FR>И почему это "подконтрольный мне" код должен делать более предлоложений о работе некоего кода Х чем другой код?
Не должен, но часто делает
Здравствуйте, koandrew, Вы писали:
_FR>>Я опять же не знаю, что такое "неподконтролен вам". "Неподконтрольный вам" == "написанный и поддерживаемый не вами (не вашим тимом/компанией)". _FR>>И почему это "подконтрольный мне" код должен делать более предлоложений о работе некоего кода Х чем другой код? K>Не должен, но часто делает
Делает, не поспоришь
Вопрос в том, должен ли ИМХО, не должен. Гораздо меньше мусора и безобразия получается, если не делить код на "наш"/"ваш", "внешний"/"внутренний". ИМХО, это всё оправдания творческой и производственной импотенции.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lexey, Вы писали:
L>У Joe Duffy в блогах было неплохое сравнение реализаций разных ReaderWriter'ов, критической секции и спинлоков. Вывод довольно забавный: readerwriter'ы в случае частой записи прилично сливают обычным критическим секциям и спинлокам.
ReaderWriterLockSlim это и есть спинлок.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, koandrew, Вы писали:
K>SRP не про то, что нельзя один и тот же класс использовать для разных целей, он про то, что конкретный экземпляр класса нужно использовать для одной цели.
Сам придумал? SRP предназначен для декомпозиции предметной области на сущности языка программирования. Экземпляры тут вообще не причем.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Сам придумал? SRP предназначен для декомпозиции предметной области на сущности языка программирования. Экземпляры тут вообще не причем.