|
|
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Здравствуйте Раньше не работал с потоками и общими данными. Голова квадратная, по этому могу тупить. Упрощенно. Допустим есть некий буфер. Размером килобайт. В начале его примерно такая структура. theader = record LockFlag: byte; ReaderCount: integer; End Последняя переменная—счетчик читателей. Исходя из того, что писать в буфер можно при наличии нуля читателей. Как я вижу работу потоков с такого рода буфером. С критическими секциями. Допустим изначально флаг блокировки none. Ну вернее флаг текущей выполняемой операции с блоком. Первый поток хочет читать. В критической секции проверяет флаг блокировки. Если none или blockread, то открываем критическую секцию, ставим флаг блокировки в blockread, увеличиваем счетчик читателей и выходим из критической секции. Далее читаем—зачитываемся. По окончании чтения опять открываем критическую секцию, уменьшаем количество читателей и если получилось ноль— ставим блокировку none. Иначе оставляем блокировку на чтение.И завершаем критическую секцию. А если хотим писать туда, то при отсутствии блокировки ставим блокировку типа blockwrite. Выходим из критической, пишем. Потом опять в критической сбрасываем блокировку в none. Пока у буфера блокировка типа blockread и readercounter не равен нулю ставить блокировку на запись не можем. Те если поток хочет осуществить запись он должен подождать , пока блокировка будет none. Единственный вопрос— а как подождать? И соответственно желающие записать должны подождать, пока блокировка не станет none. Но как? Простым циклом while? Подозреваю, что не прокатит Мысль вроде в правильном направлении, но не уверен, тк ни разу с потоками и разделяемыми буферами не работал ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.04.2019, 23:54 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergqЕдинственный вопрос— а как подождать?Самый простой и скорее всего лучший вариант - выкинуть все эти флаги и счетчики, а все действия с буфером производить внутри "открытой" критической секции, и тогда всё будет работать само. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 00:07 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
YuRocksergqЕдинственный вопрос— а как подождать?Самый простой и скорее всего лучший вариант - выкинуть все эти флаги и счетчики, а все действия с буфером производить внутри "открытой" критической секции, и тогда всё будет работать само. И об этом думал) собственно да, читателей может быть много. И они двумя критическими секциями ставятт—снимают флаги и счетчики. А ждать то для блокировки на запись вроде как надо. Ибо допустим есть 20 читателей. И тут вдруг нарисовался писатель. А он может писать только тогда, когда readercount равен нулю. Те в любом случае ему надо как то ждать, когда отвалятся все 20 читателей ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 00:14 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergqписать в буфер можно при наличии нуля читателей. А если нужен тебе RWLock, так и используй его. Он в VCL уже готовый есть. Но я бы ещё поразмыслил над задачей. Может, для пущей производительности, Copy-on-Write там будет в жилу. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 00:25 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakovsergqписать в буфер можно при наличии нуля читателей. А если нужен тебе RWLock, так и используй его. Он в VCL уже готовый есть. Но я бы ещё поразмыслил над задачей. Может, для пущей производительности, Copy-on-Write там будет в жилу. Да вроде как я и описал RWlock. Только не осилил задачу ожидания возможности записи. Хочется все ж без vcl, самому) мозги поформировать. А то последнее время разжижаются copy-on-write это когда при необходимости записи мы делаем копию буфера, модифицируем и помещаем обратно? Чет не пойму зачем так делать? Все равно ж в итоге придется вернуть модифицированные данные на место. А для этого как раз и придется ставить лок при записи обратно. Чтоб читатели не ломанулись читать недописанные данные ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 01:02 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergq Хочется все ж без vcl, самому) мозги поформировать. А то последнее время разжижаются Тогда тебе к Рихтеру, там расписаны эти примитивы. Одним мутексом не обойдёшься, надо два. sergqcopy-on-write это когда при необходимости записи мы делаем копию буфера, модифицируем и помещаем обратно? Чет не пойму зачем так делать? Все равно ж в итоге придется вернуть модифицированные данные на место. А для этого как раз и придется ставить лок при записи обратно. Чтоб читатели не ломанулись читать недописанные данные "Запись обратно" это атомарная операция присваивания одного указателя, в локе не нуждается. Старые читатели читают старый буфер, новые читатели читают уже новый. Старый освобождается при падении его счётчика ссылок до нуля. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 01:10 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakovsergq Хочется все ж без vcl, самому) мозги поформировать. А то последнее время разжижаются Тогда тебе к Рихтеру, там расписаны эти примитивы. Одним мутексом не обойдёшься, надо два. sergqcopy-on-write это когда при необходимости записи мы делаем копию буфера, модифицируем и помещаем обратно? Чет не пойму зачем так делать? Все равно ж в итоге придется вернуть модифицированные данные на место. А для этого как раз и придется ставить лок при записи обратно. Чтоб читатели не ломанулись читать недописанные данные "Запись обратно" это атомарная операция присваивания одного указателя, в локе не нуждается. Старые читатели читают старый буфер, новые читатели читают уже новый. Старый освобождается при падении его счётчика ссылок до нуля. Нездоровое желание читать и писать в один и тот же участок памяти) Можно ж теоретически через мьютекс подождать? Первый читатель со создаст мьютекс. Последний освободит. А писатель будет ждать освобождения? И кстати почему запись обратно не нуждается в локе? Операция присваивания то тоже не атомарна? Тк все ж состоит из несколько асм комманд? Только через interlocked функции. А это тоже своего рода лок. Где то тут даже вы про это писали. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 01:18 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergqОперация присваивания то тоже не атомарна? Тк все ж состоит из несколько асм комманд? Только через interlocked функции. А это тоже своего рода лок. interlocked функции, конечно, лок, но такой короткий, что на производительности практически не сказывается. И при желании можно обойтись и без них, поскольку на интеловской архитектуре для данных до размера указателя нет thorn reads, простое присваивание и чтение атомарны, это одна asm команда. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 12:38 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakovпростое присваивание и чтение атомарны, это одна asm команда Только простое присваивание и чтение. А еще всё это так в рамках одного процессора (ядра). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 12:58 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
YuRockА еще всё это так в рамках одного процессора (ядра).В смысле, что может произойти одновременное выполнение этой одной asm-команды несколькими процессорами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 13:01 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
YuRockТолько простое присваивание и чтение. Только о них я и говорю. YuRockВ смысле, что может произойти одновременное выполнение этой одной asm-команды несколькими процессорами. Может, но память-то у них всё равно общая, так что один процессор не сможет прочитать смесь из двух разных значений, записываемых остальными. То есть если в памяти лежит 12345678, а один процессор пишет 87654321, то второй никогда не получит 12344321 или 87655678. По крайней мере именно так я читаю спеки. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 13:06 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Есть ещё стандартный TMultiReadExclusiveWriteSynchronizer и его альтернативы: https://stackoverflow.com/questions/10378253/faster-tmultireadexclusivewritesynchronizer ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 13:17 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakovодин процессор не сможет прочитать смесь из двух разных значений, записываемых остальными. Хотя, конечно, это только для очень узкого класса задач. COW так не организуешь: пока ты прочитал старый указатель и пытаешься увеличить счётчик ссылок, кто-то другой его уже довёл до нуля, память освободил и ты получаешь AV. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 13:21 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergqМысль вроде в правильном направлении, но не уверен, тк ни разу с потоками и разделяемыми буферами не работал У тебя не правильный подход. Для чтения - не нужны блокировки и критические секции. Как правильно сделать чтение/запись из общих данных написано в шаблоне проектирования Блокировка с двойной проверкой Краткий смысл: 1. Прежде чем прочитать, спрашиваем - А есть ли то, что нужно прочитать? 2. Если есть - читаем. В общем-то и всё. 3. Если нет, входим в крит. секцию. 4. После входа - проверяем повторно А есть ли то, что нужно прочитать? , т.к. во время входа туда мог положить это другой поток. 5. Если данные есть - читаем. При необходимости - кладём их. Выходим из критической секции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 13:59 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovYuRockТолько простое присваивание и чтение. Только о них я и говорю. YuRockВ смысле, что может произойти одновременное выполнение этой одной asm-команды несколькими процессорами. Может, но память-то у них всё равно общая, так что один процессор не сможет прочитать смесь из двух разных значений, записываемых остальными. То есть если в памяти лежит 12345678, а один процессор пишет 87654321, то второй никогда не получит 12344321 или 87655678. По крайней мере именно так я читаю спеки. Это всё понятно. Только когда, скажем, 8 процессоров одновременно захотят увеличить данные, находящиеся в ячейке памяти, на единицу, то в результате мы можем получить, что это значение увеличилось на [от 1 до 8 как повезет]. Хотя и запись, и чтение - атомарные операции, но толку от этого будет мало. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 15:38 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
YuRock, Они будут синхронизированы между собой. Важно правильно только расставлять барьеры памяти, чтобы они понимали что данные надо брать не из собственного кеша... Хотя кеши должны синхронится между собой... https://habr.com/ru/post/196548/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 16:02 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
YuRock8 процессоров одновременно захотят увеличить данные А, так "увеличить" это совсем другая операция, я про неё не говорил. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 16:35 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
X-CiteОни будут синхронизированы между собойЕсли это сделать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 17:53 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovYuRock8 процессоров одновременно захотят увеличить данные А, так "увеличить" это совсем другая операция, я про неё не говорил.Да, не говорил. Но просто что-то прочитать и просто что-то записать - обычно, этого мало для построения логики программ :) А малейшее усложнение уже ведет к необходимости синхронизации группы команд. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 17:55 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovDimitry Sibiryakovодин процессор не сможет прочитать смесь из двух разных значений, записываемых остальными. Хотя, конечно, это только для очень узкого класса задач. COW так не организуешь: пока ты прочитал старый указатель и пытаешься увеличить счётчик ссылок, кто-то другой его уже довёл до нуля, память освободил и ты получаешь AV. Да, ну очень узкого. Даже классика - Алгоритм Деккера на современных процессорах просто так без барьеров памяти не будет работать корректно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.04.2019, 18:13 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergqДа вроде как я и описал RWlock. Только не осилил задачу ожидания возможности записи. Хочется все ж без vcl, самому) мозги поформировать. А то последнее время разжижаются самый примитивный и рабочий вариант- тынц единственное практически у всех алгоритмов нельзя с readlock-a войти во writelock ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.04.2019, 09:55 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovМожет, но память-то у них всё равно общая, так что один процессор не сможет прочитать смесь из двух разных значений, записываемых остальными. То есть если в памяти лежит 12345678, а один процессор пишет 87654321, то второй никогда не получит 12344321 или 87655678. По крайней мере именно так я читаю спеки. всё это работает когда данные выровнены + не превышают 32-бит, с границами блоков всё уже не так просто, байты могут быть вообще в разных физических планках памяти Dimitry Sibiryakovinterlocked функции, конечно, лок, но такой короткий, что на производительности практически не сказывается. они заставляют конкурирующий проц сбрасывать кэш для теста достаточно запустить несколько потоков только и делающих что изменяющих один Int, если это будет делать только один поток, то это будет раз в 5 быстрее, чем если бы это делали несколько, но это конечно такой критический вариант теста ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.04.2019, 10:06 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
sergq, Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.04.2019, 16:19 |
|
||
|
Потоки и общие данные
|
|||
|---|---|---|---|
|
#18+
Бум осмысливать всю информацию) Возник такой вопрос. По логике блокировок. Допустим применительно к базам данных. Допустим есть операция вставки. В моем понимании она происходит так. Может слегка упрощенно. 1. Поиск последней pointer page 2. На ней поиск свободного слота. 3. По номеру из слота взять data page 4. Найти на ней свободный слот для данных. 5. Записать инфу , что очередной слот занят. 6. Записать сами данные Те в операции участвуют два разделяемых блока данных. Но вроде операция над ними логически (транзакционно) едина. И может случиться так, что один тред ну задумался. Между вторым и третьим шагом. А второй тред шустро выполнил все шесть шагов. В итоге у первого треда после раздумий есть номер слота на PP с его точки зрения свободный, но на самом деле уже занят. Как в таких случаях блокировки расставляются? Как вариант. Блокируется PP, найденная на первом шаге для всех операций, кроме выборки. И так же с DP. И вся эта связка разблокируется только после того, как все последовательность операций выполнится? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2019, 16:17 |
|
||
|
|

start [/forum/topic.php?fid=58&msg=39799081&tid=2039577]: |
0ms |
get settings: |
9ms |
get forum list: |
19ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
180ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
68ms |
get tp. blocked users: |
1ms |
| others: | 239ms |
| total: | 536ms |

| 0 / 0 |
