Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Delphi |
![]() ![]() |
Топик располагается на нескольких страницах: [1] 2 вперед Ctrl→ все |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12581 |
Есть поле класса
FMessage: string
к нему идет обращение из разных потоков на чтение и запись. Нужна ли мне при этом синхронизация? Или когда я записываю новое значение в строку, Delphi всегда выделяет новый кусок памяти и я никогда не прочитаю часть строки до присвоения и часть после, С уважением, Vasilisk |
12 авг 19, 17:56 [21947440] Ответить | Цитировать Сообщить модератору |
Мимопроходящий Member Откуда: бурятский тундрюк, эсквайр Сообщений: 31976 |
12.08.2019 17:56, _Vasilisk_ пишет: > Delphi всегда выделяет новый кусок памяти и я никогда не прочитаю часть строки до присвоения и часть после, интересно послушать, что скажут монстры рока. раскапывать какая там неонка у неё внутре - долго и муторно. имхо, лучше перебдеть, чем недобдеть. Posted via ActualForum NNTP Server 1.5 |
12 авг 19, 18:12 [21947451] Ответить | Цитировать Сообщить модератору |
Kazantsev Alexey Member Откуда: Сообщений: 4988 |
Нужна. |
||
12 авг 19, 18:13 [21947452] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12581 |
function GetMessage: string; begin Lock; try Result := FMessage; finally Unlock; end; end;имеет право на существование? Или я должен писать так? function GetMessage: string; begin Lock; try Result := FMessage; UniqueString(Result); finally Unlock; end; end; По идее без UniqueString синхронизация не имеет смысла |
||||
12 авг 19, 18:21 [21947460] Ответить | Цитировать Сообщить модератору |
X-Cite Member Откуда: Минск Сообщений: 1812 |
function GetMessage: string; begin Lock; try Result := FMessage; finally Unlock; end; end; |
12 авг 19, 18:35 [21947471] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12581 |
X-Cite, Это сейчас о чем? |
12 авг 19, 18:39 [21947473] Ответить | Цитировать Сообщить модератору |
DmSer Member Откуда: Пенза Сообщений: 1316 |
Я всегда так пишу. Одной лишь CS недостаточно (вроде). В принципе, ошибки со строками довольно быстро отыскиваются, если сделать нагрузочный тест с несколькими потоками. Чем больше ядер у процессора, тем быстрее ошибка воспроизводится. От длины строки также может зависеть. |
||
12 авг 19, 18:51 [21947479] Ответить | Цитировать Сообщить модератору |
Kazantsev Alexey Member Откуда: Сообщений: 4988 |
_Vasilisk_, Насколько я помню, только чтение синхронизировать не требуется (счётчик и так синхронизируется). Синхронизация нужна в сценариях где присутствует запись. |
12 авг 19, 18:56 [21947480] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12581 |
|
||
12 авг 19, 19:00 [21947482] Ответить | Цитировать Сообщить модератору |
Kazantsev Alexey Member Откуда: Сообщений: 4988 |
|
||||
12 авг 19, 19:08 [21947485] Ответить | Цитировать Сообщить модератору |
Kazantsev Alexey Member Откуда: Сообщений: 4988 |
Вот, нашёл разъяснение от создателя: https://blog.therealoracleatdelphi.com/2015/11/friendly-reminder.html |
12 авг 19, 19:30 [21947492] Ответить | Цитировать Сообщить модератору |
ARGB32 Member Откуда: Мск Сообщений: 37 |
Так со строками получиться не может благодаря copy-on-write, но синхронизация доступа к самой переменной таки нужна. Иначе, в отличии от случая с Integer кстати, геттер может получить из другого потока строку, которая будет вот-вот разрушена и дальнейшее обращение к этой переменной приведет к AV. UniqueString() не нужен. |
||
13 авг 19, 00:48 [21947603] Ответить | Цитировать Сообщить модератору |
Голландец Member Откуда: Сообщений: 125 |
_Vasilisk_, Синхронизация нужна, unique не нужен Можно заморочиться с лок фри, но это сложно |
13 авг 19, 06:18 [21947637] Ответить | Цитировать Сообщить модератору |
DmSer Member Откуда: Пенза Сообщений: 1316 |
Лучше пусть будет. Мы же не знаем, какая работа со строкой будет в дальнейшем. А cs больше не будет. |
||
13 авг 19, 07:03 [21947640] Ответить | Цитировать Сообщить модератору |
kealon(Ruslan) Member Откуда: Нижневартовск Сообщений: 6255 |
по мне lock лучше для каждой несвязной переменной с контролем времени жизни свой сделать, по типу плюсов. например, TSync<t> = record private l: TSpinLock; v: t; function GetValue(): t; procedure SetValue(const A: t); public property Value read GetValue write SetValue; end; но мазохисты конечно встречаются везде... |
||
13 авг 19, 07:17 [21947641] Ответить | Цитировать Сообщить модератору |
Василий 2 Member Откуда: Сообщений: 1016 |
Присвоение строк просто копирует указатель на один и тот же фрагмент памяти. Лок-анлок достаточно, если ты прям железно уверен, что сама строка не меняется. Но лучше добавить и копирование, если это не станет узким местом. |
13 авг 19, 09:54 [21947720] Ответить | Цитировать Сообщить модератору |
X-Cite Member Откуда: Минск Сообщений: 1812 |
Зачем копирование, если есть лок? |
13 авг 19, 10:48 [21947778] Ответить | Цитировать Сообщить модератору |
Василий 2 Member Откуда: Сообщений: 1016 |
Может меняться содержимое строки. |
13 авг 19, 12:05 [21947904] Ответить | Цитировать Сообщить модератору |
X-Cite Member Откуда: Минск Сообщений: 1812 |
Логично же что может... Пока у вас обращение к переменной чтение/запись через блокировку то изменения строк управляемые.. Копирование тогда зачем? |
13 авг 19, 12:16 [21947923] Ответить | Цитировать Сообщить модератору |
DmSer Member Откуда: Пенза Сообщений: 1316 |
Чтобы не писать в дальнейшем при обращении к это строке Lock / Unlock |
||
13 авг 19, 12:38 [21947964] Ответить | Цитировать Сообщить модератору |
X-Cite Member Откуда: Минск Сообщений: 1812 |
Вы не к строке обращаетесь, а к переменной. Выделите абстракцию (класс/ы), перенесите туда логику связанную со строкой.. в этой абстракции обеспечьте потокобезопасность и везде используйте ее.. Методы абстракции (классов) будут потокобезопасны, вызывайте где хотите... |
||||
13 авг 19, 13:23 [21948033] Ответить | Цитировать Сообщить модератору |
kealon(Ruslan) Member Откуда: Нижневартовск Сообщений: 6255 |
как уже написали выше, проблема при взятии строки увеличение инкремента может не успеть и строку удалят в другом потоке, по-этому операции с "хранилищем" надо лочить а дальше строка защищена механизмом CopyOnWrite, если напрямую не лезть в память, то проблем с копией строки нет |
||||
13 авг 19, 13:54 [21948106] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12581 |
|
||||||||
13 авг 19, 14:30 [21948152] Ответить | Цитировать Сообщить модератору |
kealon(Ruslan) Member Откуда: Нижневартовск Сообщений: 6255 |
mov eax, [v] <- если здесь произведут декремент в другом потоке, то в eax будет ссылка на убитый кусок call _straddref т.е. при работе со строкой, interlocked функциями не обойтись |
||||||
13 авг 19, 15:13 [21948209] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12581 |
function _UStrClr(var S): Pointer; var P: PStrRec; begin if Pointer(S) <> nil then begin P := Pointer(PByte(S) - SizeOf(StrRec)); Pointer(S) := nil; if P.refCnt > 0 then begin if AtomicDecrement(P.refCnt) = 0 then FreeMem(P); end; end; Result := @S; end; |
||
13 авг 19, 15:16 [21948216] Ответить | Цитировать Сообщить модератору |
Топик располагается на нескольких страницах: [1] 2 вперед Ctrl→ все |
Все форумы / Delphi | ![]() |