109: (Default)
[personal profile] 109
http://msdn.microsoft.com/en-us/magazine/cc163744.aspx

For a lock to provide mutual exclusion for a region of memory, no writes to that memory can occur without entering the same lock. In a properly designed program, associated with every lock is a region of memory for which it provides mutual exclusion. Unfortunately, there is no obvious artifact of the code that makes this association clear, and yet this information is absolutely critical for anyone reasoning about the multithreaded behavior of the program.

what would be the ideal syntax? what comes to mind is

object myLock = new object();
[Protected(myLock)] MyState myState;
x-posted

(no subject)

Date: 2008-07-24 05:28 am (UTC)
From: [identity profile] anton-solovyev.livejournal.com
synchronized в Java удобно решает проблемы с concurrency и не мешается под ногами. Не совсем понятно в чем тут issue.

(no subject)

Date: 2008-07-24 08:42 am (UTC)
From: [identity profile] 109.livejournal.com
Антон, не позорься :)

(no subject)

Date: 2008-07-24 03:28 pm (UTC)
From: [identity profile] anton-solovyev.livejournal.com
Ok, whatever. Я просто пишу, что проблем, вроде, нет, чисто практически. Вроде это все уже более-менее пройденный этап.

(no subject)

Date: 2008-07-24 08:32 pm (UTC)
From: [identity profile] 109.livejournal.com
там в статье довольно простым языком объясняется, почему просто залупить [Synchronized] - далеко не всегда адекватно.

(no subject)

Date: 2008-07-24 09:33 pm (UTC)
From: [identity profile] anton-solovyev.livejournal.com
Смотрел еще, не увидел.

(no subject)

Date: 2008-07-24 09:46 pm (UTC)
From: [identity profile] anton-solovyev.livejournal.com
Или ты имеешь ввиду замечание о том, что последовательность синхронизироанных getter'ов может не возвращать consistent view объекта? Ну так для этого нужно возвращать consistent snapshot одним вызовом (там внизу у msh возвращается tuple (name, wight, height)). Также нужно возвращать клоны, а не references на внутренние объекты. Но это все как бы само собой.

(no subject)

Date: 2008-07-25 12:38 am (UTC)
From: [identity profile] 109.livejournal.com
jeez! (c)

объявить класс synchronized - это всё равно что обернуть каждый метод, включая сеттеры и геттеры, в lock(this). для одних задач слишком много, для других слишком мало. в статье приводятся многочисленные примеры (hashtable buckets, например).

(no subject)

Date: 2008-07-24 12:26 pm (UTC)
From: [identity profile] faceted-jacinth.livejournal.com
Какая-то фигня, по-моему.

Во-первых, зачем отдельный myLock, если точно так же можно лочить само myState (и подразумевается, что оно действительно лочится при каждом доступе)?

Во-вторых, это вовсе не решает проблемы. Доступ к полям myState и так практически всегда атомарный, там лок и не нужен. Лок нужен для обеспечения более длительных операций, типа "считать из myState состояние, что-то сделать, записать в myState новое состояние", а никакой компилятор не сможет автоматически угадать, что ты имеешь в виду, какую именно подпоследовательность операций ты хочешь сделать атомарной. Более того, он не должен заниматься таким угадыванием, потому что одна ошибка - и пиздец, причём пиздец вовсе не мгновенный и ясно видимый, а наоборот неслышно крадущийся в зарослях и выжидающий.

(no subject)

Date: 2008-07-24 12:30 pm (UTC)
From: [identity profile] faceted-jacinth.livejournal.com
Тут, скорее, можно методы помечать атрибутами, типа [Synchronized(myState)] public void ProcessSomething(Something something) { bla bla bla }

Но, с другой стороны, это не намного короче/понятней, чем тупой lock(myState) { bla bla bla } внутри (в который такой атрибут и будет, собственно, раскрываться).

(no subject)

Date: 2008-07-24 08:29 pm (UTC)
From: [identity profile] 109.livejournal.com
во-первых, читай мой ответ msh.

во-вторых, предложенный синтаксис решает не проблему собственно локинга, а проблему "there is no obvious artifact of the code that makes this association clear". то есть, после добавления такого атрибута компилятор (если может), или рантайм (если компилятор не может) должны бросать ошибку типа "attempt to access shared resource myState when myLock is not acquired".

зачем отдельный lock, про это много литературы написано, в том числе и по ссылке. но если девелопер считает, что он знает лучше, он может написать [Protected(myState)] MyState myState; или там просто [Protected] myState, что то же самое, что, как ты написал, [Synchronized] myState, ну или так, как Антон написал, как в джаве делается.

(no subject)

Date: 2008-07-24 08:43 pm (UTC)
From: [identity profile] faceted-jacinth.livejournal.com
Ну, может быть, может быть.

Правда, есть ряд сложностей. Во-первых, такая запись может вызвать Ложное Чувство Защищённости™. Во-вторых, далеко не всегда ресурс == один объект. А так -- да, в принципе довольно правильная штука.

(no subject)

Date: 2008-07-25 12:43 am (UTC)
From: [identity profile] 109.livejournal.com
далеко не всегда ресурс == один объект.

object myLock = new object();
[Protected(myLock)] MyState myState;
[Protected(myLock)] MyState2 myState2;

Ложное Чувство Защищённости

да, примерно так же, как automatic memory management вызывает ложное чувство защищённости от memory leaks.

(no subject)

Date: 2008-07-25 07:51 am (UTC)
From: [identity profile] faceted-jacinth.livejournal.com
Я о том, что после этого компилятор будет совершенно удовлетворён, если ты сделаешь
lock(myLock)
{
tmp = myState;
}

lock(myLock)
{
myState2 += tmp;
}

Тогда как на самом деле всё должно было происходить внутри одного и того же лока, например. Или не должно. Но компилятор больше не ругается. Вдобавок этой штукой, видимо, переменные, а не объекты защищаются, поэтому ссылка может утечь и компилятор ничего не скажет.


Но в целом да, идея вполне правильная. Её даже наверное можно реализовать сторонней тулзой (или на базе fxCop'a какого-нибудь).

(no subject)

Date: 2008-07-25 05:14 pm (UTC)
From: [identity profile] 109.livejournal.com
ну да, during compile-time, очевидно, только переменные можно защитить. а в рантайме можно и объекты. хотя я с утра плохо соображаю. например, не могу понять, что такого thread-unsafe в коде, который ты написал.

(no subject)

Date: 2008-07-25 05:55 pm (UTC)
From: [identity profile] faceted-jacinth.livejournal.com
Объекты нельзя защищать потому что совершенно непонятна семантика - насколько глубоко защищать-то. Поля объектов ведь тоже содержат объекты иногда, а то и целые коллекции.

А кодом я, видимо, что-то имел в виду, но сам не пойму уже. Неважно, в общем смысл понятен, наверное.

(no subject)

Date: 2008-07-31 07:41 pm (UTC)
From: [identity profile] 109.livejournal.com
в смысле, насколько глубоко? точно так же, как Synchronized защищает, непосредственные свойства и методы объекта. эдак ведь тоже можно вытащить Synchronized reference type и менять его сколько влезет не-thread-safe способом.

смысл твоего кода неожиданно стал понятен :)
ну да, эта проблема существует и сейчас, никуда не девается, но при чём здесь? повторить, какую проблему решает предложенный мной синтаксис? :)

(no subject)

Date: 2008-07-24 02:20 pm (UTC)
From: [identity profile] msh.livejournal.com
For a lock to provide mutual exclusion for a region of memory, no writes to that memory can occur without entering the same lock.

Это ерунда какая-то. Лок используется чтобы сериализовать исполнение неатомарной операции. Writes совершенно непричем, write может быть атомарным и не требовать защиты, read может требовать защиты без всяких write

(no subject)

Date: 2008-07-24 08:21 pm (UTC)
From: [identity profile] 109.livejournal.com
нет (с)

защищаются всегда ресурсы, не куски кода. кусок кода нужно защищать лишь постольку, поскольку он работает с ресурсом и только на время, пока нарушается инвариант. там в статье всё объясняется простым языком, для dummies :)

(no subject)

Date: 2008-07-24 08:41 pm (UTC)
From: [identity profile] msh.livejournal.com
Oh, jeez

thread 1:

name = person.getName();
height = person.getHeight();
weight = person.getWeight();

thread 2:

printf("Name: %s weight %d height %d\n", name, height, weight);

какой конкретно ресурс тут защитит лок, гарантирующий что мы печатаем имя и вес одного человека?

(no subject)

Date: 2008-07-25 12:30 am (UTC)
From: [identity profile] 109.livejournal.com
воистину jeez.

name, height and weight, которым присваиваются значения, это свойства какого объекта? вот у этого объекта и нарушается инвариант, его и надо лочить. или подробнее надо?

(no subject)

Date: 2008-07-25 01:21 am (UTC)
From: [identity profile] msh.livejournal.com
Это три разных объекта. Существуют внутри четвертого, которые делает стописят разных операций. Это операция номер 109, остальные 141 также требуют тех или иных локов

Так чо, где тут ресурс-то?

(no subject)

Date: 2008-07-31 07:29 pm (UTC)
From: [identity profile] 109.livejournal.com
(повторение - мать учения) ресурс - то, у чего нарушается инвариант. в данном случае - [disjoint] set of memory locations { name, height, weight }. всё остальное, начиная с этого момента - это design choice, про который я готов рассуждать только в объектно-ориентированных рамках.

в рамках же описанного тобой замечательного дизайна ближайший объект, накоторый мапится этот disjoint set, это объект №4. и да, если его лочить, concurrency будет хуёвая, и кто в этом виноват?

дальше тут можно очень много слов сказать о том, как сделать лучше, но это всё будет в основном про оо дизайн, а не про мультитредность. в хорошем оо дизайне редко возникают вопросы, куда смапить инвариант; само наличие инварианта является фактором, влияющим на дизайн.

безусловно, бывают исключения, и я даже готов про них поговорить, но только в оо рамках. и я бы таки порекомендовал сначала статью прочитать, ибо там на многие простые вопросы очень хорошо отвечено, а то будет как с соловьёвым.

(no subject)

Date: 2008-07-25 12:25 am (UTC)
From: [identity profile] 109.livejournal.com
непричем

извени! :)
можешь привести пример, когда read без write требует защиты?

(no subject)

Date: 2008-07-31 07:30 pm (UTC)
From: [identity profile] 109.livejournal.com
хочу всё знать! (про read без write, который требует защиты)

(no subject)

Date: 2008-07-28 01:52 am (UTC)
From: [identity profile] sasha-gil.livejournal.com
Что ты думаешь о перспективах TM в .NET?

(no subject)

Date: 2008-07-28 08:12 am (UTC)
From: [identity profile] 109.livejournal.com
шо це такэ?

(no subject)

Date: 2008-07-28 08:55 am (UTC)
From: [identity profile] sasha-gil.livejournal.com
Transactional memory, однако. Имеется в виду software transactional memory - как средство облегчить жизнь кодерам, которым нужно отчитаться перед начальством "многопоточность успешно освоена!", не заморачиваясь при этом с локами. Но и не имея особого выигрыша в производительности (но и не имея геморроя, заметь). Подробности письмом / при личной встрече, если хочешь.

(no subject)

Date: 2008-07-28 09:36 pm (UTC)
From: [identity profile] 109.livejournal.com
а, transactional memory! читал про неё, да, когда исследовал non-blocking aka lock-free synchronization.

на словах, вроде, всё гладко. надо посмотреть на implementation каакой-нибудь. что меня прикололо, когда я читал, это что вначале декларируется non-blocking, а потом не только "in case of conflict transaction will wait before retry" (т.е. blocking), а и просто-таки все упомянутые там implementations internally всё равно используют locks.

неочевидно, поможет ли это рядовому девелоперу, или наоборот. сейчас я не должен вникать в то, каков именно у меня инвариант, который не должен нарушаться, достаточно знать, какие переменные/объекты в нём участвуют, и закрыть их локом, что гарантирует защиту инварианта от внешних воздействий. в том смысле, что только я сам могу его нарушить.

при tm же, см. раздел "implementation issues", внутри атомного блока инвариант не гарантирован, хотя именно там-то он мне и важен.

(no subject)

Date: 2008-07-28 09:37 pm (UTC)
From: [identity profile] 109.livejournal.com
при личной встрече, да! пивка же надо как-нибудь собраться попить.

(no subject)

Date: 2008-07-28 10:18 pm (UTC)
From: [identity profile] 109.livejournal.com
посмотрел две имплементации - ms и вот эту. получается, что вместо того, чтобы заморачиваться с локами, девелопер должен заморачиваться с синтаксисом STM подсистемы, и плюс ещё свои shared data classes писать специальным образом.

Profile

109: (Default)
109

March 2019

S M T W T F S
     12
3456789
101112131415 16
17181920212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags