|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvИзопропилпропущено... да, это так.Нет, это не так. volatile и сериализует доступ к конкретной переменной (напр. к long на 32-битной платформе), и является примитивом синхронизации благодаря окружающим его барьерам памяти. Покажи код где этот "примитив синхронизации" таки синхронизирует доступ двух потоков к одним и тем же данным. Сериализация доступа к переменным не дает вообще ничего. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:23 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvДа, так и есть. Просто криворукие разработчики .Net решили не давать гарантии атомарности long/double, из-за чего и возник весь сыр-бор с невозможностью объявить их volatile, а оттуда же выросли проблемы с дженериками, которые так же нельзя объявить волатилями. Одно тупое решение какого-то неквалифицированного индуса, и API .Net превратился в гомно. Операции с: volatile int a; Точно также не атомарны. Ради всех цвятых, открой букварь и почитай. Зачем демонстрировать безграмотность? Открыл, почитал, всё понял, закрыл, поумнел = больше не говоришь глупостей. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:24 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvЧто я не понимаю? То что волатильность доступа не дает ничего с точки зрения синхронизации потоков. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:25 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvиспользуют volatile / Interlocked для попытки быстрого захвата ресурса нельзя можно использовать для захвата ресурсов. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:26 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjv, Да ты даже в Java, как оказывается, ни черта не петришь. JEREMY MANSONIf a variable is declared as volatile, it means that it is expected to be modified by multiple threads. Naturally, you would expect the JRE to impose some form of synchronization for volatile variables. As luck would have it, the JRE does implicitly provide synchronization when accessing volatile variables, but with one very big caveat: reading a volatile variable is synchronized and writing to a volatile variable is synchronized, but non-atomic operations are not . What this means is that the following code is not thread safe : Код: java 1.
The previous statement could also be written as follows: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
In other words, if a volatile variable is updated such that, under the hood, the value is read, modified, and then assigned a new value, the result will be a non-thread-safe operation performed between two synchronous operations. You can then decide whether to use synchronization or rely on the JRE's support for automatically synchronizing volatile variables. The better approach depends on your use case: If the assigned value of the volatile variable depends on its current value (such as during an increment operation), then you must use synchronization if you want that operation to be thread safe . ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:35 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvУгу, не используется. Например, вот здесь это не используется http://referencesource.microsoft.com/#mscorlib/system/threading/SpinLock.cs Синхронизация обеспечивается не волатильностью, а interlocked - атомарными операциями. И это не одно и тоже. Волатильность нужна чтобы разные процессоры не считали что у одно и того же лока в один и тот же момент времени разные владельцы. Причем если убрать "владельца", то можно синхронизацию запилить и без volative (получится классический lock-free). ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:35 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvhVosttВот где твой косяк в отношении понимания модификатора volatile и «волатильным» чтением/записью. И ещё, кажется, что ты путаешь volatile с Interlocked , последний гарантирует атомарность операции, в то время как volatile — отнюдь не гарантирует.Да, так и есть. Просто криворукие разработчики .Net решили не давать гарантии атомарности long/double, из-за чего и возник весь сыр-бор с невозможностью объявить их volatile, а оттуда же выросли проблемы с дженериками, которые так же нельзя объявить волатилями. Одно тупое решение какого-то неквалифицированного индуса, и API .Net превратился в гомно. Это не тот же индус, котрый придумал AtomicInteger в Java? http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:44 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
Ладно, с кривотой volatile я разобрался. Причина: какой-то индус-студент, пришедший в Microsoft набраться опыта, решил не давать гарантии атомарности чтений/записей типам long/double, хотя это сделать эелментарно (хотя бы просто делеировать в Interlocked). Потом через какое-то время появились дженерики, за которыми могли стоять все те же long и double. Но вместо того, что бы снять это ограничение (а из-за этого legacy код бы совершенно не пострадал), другой индус-студен решил запретить volatile и для дженериков. Из-за этого мы имеем кривой и косой API. Проехали. Следующая кривота. ThreadPool. Такого маразма я давно не видел: 1) Какой идиот решил сделать его общим на все приложение? Что он курил? 2) И зачем он смешал воедино обычныйе треды-воркеры и треды для completion ports? 3) И почему он не дал нам возможность нормально сконфигурировать его? Теперь расскажите мне, господа дотнетовцы, как вы будете решать следующие задачи с помощью этого уродца: 1) У вас в приложении генерируются задачи, которые надо выполнять последовательно одну за другой по мере их появления (примерно как это сделано с UI). Как вы этого будете делать? В Java я могу создать отдельный тред пул с ровно одним потоком, и класть в него задачи. Одна строчка кода. В .Net мне надо изобретать свой велосипед с while-циклами, блокирующими колелкциями и прочим дерьмом, которое характерно для тред-пулов. 2) Вы делаете нечто вроде map-reduce фреймворка. Пользователь дает вам задачи, вы их кладете в тред-пул. Каждая задача может сгенерировать другие задачи, которые пойдут в этот же тред-пул, и т.д.. Но кроме пользовательских задач, у вашего приложения еще есть свои системные задачи, которые должны быть гарантированно исполнены и исполнены быстро. Вопрос на засыпку - сможете ли вы использовать ThreadPool в этом случае? Хрен вам, господа! Ведь если юзерские задачи засрут вам пул, то время выполнения вашей системной задачи будет расти пропорционально размеру очереди пользовательских задач. И опять - пищем свои велосипеды. А в Java надо просто создать два разных пула - один для пользователей, один для себя. И все. Очередному индусу в программистском угаре пришла в голову идея сделать ThreadPool статическим, и все - вся идея тут же становится ограниченной и корявой. А надо то было просто конструкторик ThreadPool сделать публичным, что бы разработчики могли создавать свои пулы. Пару строчек кода поленились добавить. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:45 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjv, А расскажи честно, зачем тебе volatile вообще понадобился? Пример кода приведи. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:48 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjv, автор Он их не отличает я Вы что то мне приписываете, я где то сказал что это особая инструкция? авторкоторые гарантируют частичную синхронизацию состояний кешей между собой вот про это поподробней расскажите пож. если вы про MemoryBarrier то это фактический сброс кеша с последующим объявлением его не действительным- вот и вся синхронизация, или там есть еще какое то шаманство? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 00:49 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjvЛадно, с кривотой volatile я разобрался. Причина: какой-то индус-студент, пришедший в Microsoft набраться опыта, решил не давать гарантии атомарности чтений/записей типам long/double, хотя это сделать эелментарно (хотя бы просто делеировать в Interlocked). Потом через какое-то время появились дженерики, за которыми могли стоять все те же long и double. Но вместо того, что бы снять это ограничение (а из-за этого legacy код бы совершенно не пострадал), другой индус-студен решил запретить volatile и для дженериков. Из-за этого мы имеем кривой и косой API. Проехали. Этой гарантии точно также нет и в Java. Нельзя "делегировать" Interlocked, так как volatile и Interlocked -- разные вещи. Ты решил с бараньей упёртостью отстаивать свою безграмотность? Вопрос. Зачем? Я понимаю, шуты причиняют себе вред, ради смеха аудитории, а у тебя какие цели? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 01:10 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
Где-то в степивот про это поподробней расскажите пож. если вы про MemoryBarrier то это фактический сброс кеша с последующим объявлением его не действительным- вот и вся синхронизация, или там есть еще какое то шаманство?Нет. Барьер - это не "сброс кэша". Никакого "сброса кэша" не существует. Если забыть про JIT, и рассматривать только железо, то "барьерные инструкции" (напр. с префиксом lock на x86), делают две вещи: 1) При записи, перед тем как ее завершить, ядро ждет, пока store buffer его кэша не флашнется, то есть пока информация о предыдущих записях, которые были сделаны этим ядром, но пока что видны только ему (см. store forwarding), не станет "видна" другим ядрам. "Видна" - это значит, что другие ядра получили запрос на инвалидацию измененных ячеек в своих кэшах. 2) При чтении, перед тем, как ее осуществить, ядро должно обработать свою invalidate queue, то есть применить все запросы на инвалидацию, полученные ранее от других ядер, но еще не обработанные. В этом и есть суть "частичной синхронизации" кэшей разных ядер при выполнении бареров. Кроме того, барьеры запрещают ядрам делать out-of-order execution в их окрестностях. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 01:21 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
cdtyjv1) У вас в приложении генерируются задачи, которые надо выполнять последовательно одну за другой по мере их появления (примерно как это сделано с UI). Как вы этого будете делать? В Java я могу создать отдельный тред пул с ровно одним потоком, и класть в него задачи. Одна строчка кода. В .Net мне надо изобретать свой велосипед с while-циклами, блокирующими колелкциями и прочим дерьмом, которое характерно для тред-пулов. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Но в эпоху тотальной асинхронности это не модно, гораздо моднее так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Но есть подозрение что тебе достаточно будет сделать просто асинхронные методы и асинхронные EventHandler_ы. cdtyjv2) Вы делаете нечто вроде map-reduce фреймворка. Пользователь дает вам задачи, вы их кладете в тред-пул. Каждая задача может сгенерировать другие задачи, которые пойдут в этот же тред-пул, и т.д.. Но кроме пользовательских задач, у вашего приложения еще есть свои системные задачи, которые должны быть гарантированно исполнены и исполнены быстро. Вопрос на засыпку - сможете ли вы использовать ThreadPool в этом случае? Хрен вам, господа! Ведь если юзерские задачи засрут вам пул, то время выполнения вашей системной задачи будет расти пропорционально размеру очереди пользовательских задач. И опять - пищем свои велосипеды. А в Java надо просто создать два разных пула - один для пользователей, один для себя. И все. А в .NET вообще не надо пулы создавать, надо воспользоваться подходящим TaskScheduler, например этим - http://code.msdn.microsoft.com/Samples-for-Parallel-b4b76364/sourcecode?fileId=44488&pathId=1649437731 cdtyjvОчередному индусу в программистском угаре пришла в голову идея сделать ThreadPool статическим, и все - вся идея тут же становится ограниченной и корявой. А надо то было просто конструкторик ThreadPool сделать публичным, что бы разработчики могли создавать свои пулы. Пару строчек кода поленились добавить. Ты снова пытаешься паттерны Java натянуть на .NET. В .NET пул потоков - деталь реализации, не предназначенная для того чтобы там чето самостоятельно шедулить. А то что ты хочешь использовать называется TaskPool (часть TPL) и возможности гораздо шире, чем может предоставить Java. Для особо жестких случаев, когда тасков много и надо нетрививально синхронизировать их между собой есть TPL Dataflow, для твоего первого вопроса надо будет написать так: Код: c# 1. 2. 3. 4. 5. 6.
Что-то похожее есть в RX, но ориентированное на потоки данных . ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 01:55 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
О, Свеном отчаялся самостоятельно справиться со своей задачей и вбросил так, чтобы ему код дали. Почему не создать конкретный топик "Не могу решить вот такую задачу. Помогите.", как это делают остальные? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 02:29 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
Где-то в степи летучесть это фишка записи и чтения данных процессора в контексте его кеша( процессора), если два разных потока крутятся на разных ядрах , работат с переменными оптимизирована через кеш каждого процессора, то есть фактическое изменение переменной задерживается в кеше, а если оно задерживается то второе ядро не может получить реальное значение. volatile дает команду процессору изменить значение переменной минуя ее копию в кеше ( сквозное изменение) и автоматом объявляет кеш не действительным - отсюда и вся гадость со скоростью доступа к кешу ядра ( приходится опять заныривать в оперативку). "летучесть это фишка записи" - Это пять , осталное - ересть. Читать про когерентность кеша. volatile кешем не управляет. Не редкое заблуждение. @cdtyjv " в 64-битной среде, у меня есть ссылка, она занимает 8 байт" В яве не всегда. Смотреть здесь @cdtyjv "2) И зачем он смешал воедино обычныйе треды-воркеры и треды для completion ports?" В CLR два пула. Второй работает с ассинхронным чтением. Строится на основе WinAPI с использованием OVERLAPPED. Много пулов: Подобное решается с использованием scheduler. @hVostt "А конкретно ты можешь «волатильно» прочитать и записать любой тип." @hVostt "Операции с: volatile int a; Точно также не атомарны." Реч конкретно про операцию чтения, а ты обобщяеш. Про общий случай "какой-то операции" речи не было. Или ты утверждаеш что чтение/запись для инт-а не атомарны? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 16:17 |
|
Почему в .Net такие кривые Lock'и?
|
|||
---|---|---|---|
#18+
mikron@hVostt "А конкретно ты можешь «волатильно» прочитать и записать любой тип." @hVostt "Операции с: volatile int a; Точно также не атомарны." Реч конкретно про операцию чтения, а ты обобщяеш. Про общий случай "какой-то операции" речи не было. Или ты утверждаеш что чтение/запись для инт-а не атомарны? Взяли int, что-то с ним сделали, вернули на место. Операция не атомарная. На счёт того, что один читатель, другой писать, тогда ОК, но я об этом уже сказал. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2014, 16:23 |
|
|
start [/forum/topic.php?fid=20&gotonew=1&tid=1402671]: |
0ms |
get settings: |
13ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
38ms |
get topic data: |
9ms |
get first new msg: |
8ms |
get forum data: |
5ms |
get page messages: |
64ms |
get tp. blocked users: |
1ms |
others: | 328ms |
total: | 483ms |
0 / 0 |