Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
4 / 3 / 1
Регистрация: 23.12.2013
Сообщений: 39
RAD XE3+

Можно ли обратиться из двух разных потоков к полям другого класса?

18.12.2023, 00:03. Показов 2006. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день! Имеется ПОТОК1 и ПОТОК2 (TThread). Есть Класс1 отнасследованный от TObject.
Суть в том что в Потоке1 происходит заполнение Поля Класс1.msg1. Далее Поток1 делает синхронизацию Вызывает метод Класс1.Sync в данном методе по мере необходимости происходит копирование Класс1.msg2 := Класс1.msg1;
ПОТОК2 Обрабатывает то что находиться Класс1.msg2, но это делает тогда когда точно не происходит Копирования msg1 в msg2. Т.е. одновременного обращения записи/чтения к одному и тому же полю из разных потоков класса1 отсутствует. Но мне не понятно, могу ли я вообще обращаться к одному классу из разных потоков? Это может привести к какой-то ошибке? Или все таки нельзя обращаться к одному классу из двух потоков, даже если поля разные?.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
18.12.2023, 00:03
Ответы с готовыми решениями:

Возможно ли члену класса обратиться к полям другого класса в котором он находится?
Есть, к примеру, код: enum TYPE{/*...*/}; class A { uint64_t data; }; class Column { std::vector<A> data;

Обратиться к полям текущего класса из методов другого
Создать два класса - в первом объявить несколько полей в private секции. Обратиться к этим полям из методов второго класса. Один класс...

Как можно обратиться к wpf контролам из другого класса
<Grid Margin="5"> <TextBlock x:Name="speed_xaml" HorizontalAlignment="Left" Margin="10,7,0,0" TextWrapping="Wrap" Text=""...

32
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,495
07.07.2024, 14:38
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Менеджер памяти может переписать в любое время адрес по этому указателю (если ему понадобится перенести объект фактически в непрерывный участок памяти)?
С чего бы вдруг? Адрес объекта сам по себе не меняется. Если бы он менялся, то программа просто не могла бы знать, когда это произошло и какой теперь адрес у объекта.
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
07.07.2024, 15:02
Цитата Сообщение от AzAtom Посмотреть сообщение
Адрес объекта сам по себе не меняется
А вот именно поэтому я и начал задавать вопросы.
Экземпляр имеющий внутри себя динамический массив, сменит только указатель на "конкретное измерение" если ему не будет хватать непрерывной памяти?
Либо если это что-то "самодельное", на основе статических массивов(для скорости) и требует переинициализации при изменении размеров(конечно пример немного притянут, но мы в фоне сначала скопируем все поля объекта в текущем их состоянии, а потом заменим ссылку на него)?

Я вообще к тому что гарантии никто не даёт, и доступ к указателю на экземпляр никто не советует разграничивать крит. секцией, ибо тогда все плюсы многопоточности потеряются...
но потоки таки читают начальный адрес экземпляра по указателю?
Если мы руками не прописываем запомнить в локальной переменной потока нужный адрес, то каждый раз будет чтение указателя на экземпляр класса не защищённое крит. секцией?
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,495
07.07.2024, 16:17
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Экземпляр имеющий внутри себя динамический массив, сменит только указатель на "конкретное измерение" если ему не будет хватать непрерывной памяти?
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type
  TIntArray = array of integer;
 
procedure TForm1.SomeProc(a2: TIntArray);
begin
 
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  a: TIntArray;
begin
  SomeProc(a);
end;
Тут да, передаётся адрес данных, который может измениться при изменении размера массива.

Но если сделать
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type
  PIntArray = ^TIntArray;
  TIntArray = array of integer;
 
procedure TForm1.SomeProc(a2: PIntArray);
begin
 
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  a: TIntArray;
begin
  SomeProc(@a);
end;
то будет передан адрес переменной a: TIntArray; который уже содержит адрес данных. И даже если поменять размер массива, то доступ к данным останется. Ну и обращаться к массиву нужно через синхронизацию, конечно, а то не исключена смена адреса массива во время обращения к нему потока. Тогда хорошо, если выскочит AV.
1
 Аватар для krapotkin
6854 / 4680 / 1465
Регистрация: 14.04.2014
Сообщений: 20,684
Записей в блоге: 21
07.07.2024, 18:00
верно
продолжая аналогию с адресами, надо иметь не сам адрес, а место, где этот адрес будет лежать, в случае когда путешественник часто переезжает, но адрес своего текущего места хранит где-то и уже вот это место точно не меняется

и еще раз - менеджер не может ничего поменять сам
только по команде
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
07.07.2024, 18:38
Цитата Сообщение от krapotkin Посмотреть сообщение
и еще раз - менеджер не может ничего поменять сам
только по команде
но есть всякие моменты навроде мы берём хендл битмапа и делаем там что-то напрямую ковыряясь в битах картинки.
Но стоит вызвать ф-цию канваса, и хендл уже invalid поскольку менджер памяти перевыделил её, а мог бы подставить по прежнему указателю или обновить его.
тут уже я не берусь судить насколько это правильно... вроде на ровном месте затраты на выделение новых адресов и удаление старых.

Добавлено через 3 минуты
Цитата Сообщение от Иван Ежик Посмотреть сообщение
тут уже я не берусь судить
Эта тема слишком глубока и затрагивает вопросы того чем руководствовались разработчики на момент разработки, что несомненно не может соответствосать ожиданиям других разработчиков.
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,495
07.07.2024, 18:53
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Но стоит вызвать ф-цию канваса, и хендл уже invalid
Дельфийский Canvas это довольно таки "вещь в себе". Может и пересоздаёт битмап при некоторых операциях, не знаю. По крайней мере, при работе с ним нельзя надеяться, что какой-то хэндл будет вечным.

Цитата Сообщение от Иван Ежик Посмотреть сообщение
менджер памяти перевыделил её, а мог бы подставить по прежнему указателю или обновить его.
Не мог бы. Менеджер памяти просто выделяет кусок памяти и возвращает её адрес, а обновлять эти адреса должна уже программа сама в своих же переменных.
0
 Аватар для krapotkin
6854 / 4680 / 1465
Регистрация: 14.04.2014
Сообщений: 20,684
Записей в блоге: 21
07.07.2024, 19:31
Цитата Сообщение от Иван Ежик Посмотреть сообщение
мы берём хендл битмапа
не путаем теплое с мягким
handle - это ID системного(!) ресурса, которым оперирует ОС
Поэтому для операций, где важна консистентность, мы обязаны его ЗАПРОСИТЬ(ЗАЛОЧИТЬ)! и ОТПУСТИТЬ!
В данном случае МП по отношению к ОС ведет себя как программа по отношению к МП.
При этом ОС залоченную память тоже не сменит. И залоченный хендл не поменяет.

МП берет большие куски памяти у ОС, получая на них хендлы, и потом отдает. Медленно.
А нам выдает по требованию. Быстро.
Вот все для чего он нам нужен.
Но сам ничего поменять не может
1
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
08.07.2024, 13:28
Цитата Сообщение от krapotkin Посмотреть сообщение
Но сам ничего поменять не может
Но если попробовать пример с "доступом к памяти битмапа напрямую, а потом нарисовать на нём средствами канваса", то при следующем доступе напрямую будет AV...Кто-то поменял его расположение в памяти, хотя размер битмапа не поменялся.
Цитата Сообщение от krapotkin Посмотреть сообщение
не путаем теплое с мягким
Да, я ошибся в формулировке, имел в виду прямой доступ к памяти картинки

Добавлено через 4 минуты
Цитата Сообщение от AzAtom Посмотреть сообщение
Ну и обращаться к массиву нужно через синхронизацию, конечно, а то не исключена смена адреса массива во время обращения к нему потока.
Так а с экземплярами класса это как работает? Я к тому что рекомендуют синхронизировать доступ к полям но не к самой переменной экземпляра(которая являясь ссылочным типом по сути и есть указатель, но который не может быть изменён с помощью арифметики указателей)

Добавлено через 1 минуту
Цитата Сообщение от AzAtom Посмотреть сообщение
По крайней мере, при работе с ним нельзя надеяться, что какой-то хэндл будет вечным.
Я ошибся, не хендл имел в виду а доступ к памяти картинки...
0
 Аватар для krapotkin
6854 / 4680 / 1465
Регистрация: 14.04.2014
Сообщений: 20,684
Записей в блоге: 21
08.07.2024, 14:36
Память картинки, если эта картинка - системный ресурс (а в VCL это именно так) - закрыта
Поэтому берем хендл и далее по списку...
В частности, потому что все форматы и JPEG и PNG ложатся в единый системный bmp, с которым GDI только и умеет работать.

В FMX уже ввели TBitmapSurface - там просто голые данные, никто их не заберет.

Цитата Сообщение от Иван Ежик Посмотреть сообщение
рекомендуют синхронизировать доступ к полям
Рекомендации не бывают исчерпывающими.
Нужен контекст
У каких-то объектов поля все время текут
Например List будет все время изменять свой внутренний массив, т.е. ссылка на него будет меняться
поэтому надо лочить сам List, брать массив, делать что-то , отпускать List.

Со строкой, насколько я помню, еще интереснее.
Объект может поменять поле-строку, в этом случае ссылка на нее изменится, но предыдущая ссылка будет содержать старую строку. Без AV.
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,495
08.07.2024, 14:45
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Я к тому что рекомендуют синхронизировать доступ к полям но не к самой переменной экземпляра
Переменная объекта и называется полем. Не пойму, в чём проблема. Пока существует экземпляр объекта, его поля тоже на месте.

Цитата Сообщение от Иван Ежик Посмотреть сообщение
имел в виду а доступ к памяти картинки
У меня с этим проблем не было. Можно пример с таким эффектом?

При старте программы создал bitmap нужного размера, записал адрес начало битов в свою переменную и затем рисую на этом bitmap как средствами canvas, так и напрямую пишу в память - работает без проблем.
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
08.07.2024, 15:31
Цитата Сообщение от krapotkin Посмотреть сообщение
Память картинки, если эта картинка - системный ресурс (а в VCL это именно так) - закрыта
Поэтому берем хендл и далее по списку...
Но сканлайн с примерами показывает как работать с памятью картинки, и предупреждений не пишет что внутри работает с хендлом.Так же ничто не мешает менять адрес указателя для доступа в нужное место памяти картинки.
(так собственно всё и работает, и до первого косяка вникать что под капотом реализации не нужно )
Цитата Сообщение от AzAtom Посмотреть сообщение
У меня с этим проблем не было. Можно пример с таким эффектом?
Я думаю несколько лет назад это упоминал тут на форуме.
Если коротко то нужно было нарисовать рамку на распознанном на картинке объекте, я долго не мог понять почему появлялись AV...
А сделано было так

begin
Читаем память картинки напрямую, распознаём;
Рисуем рамку или сдвигаем окно если не удалось.
Проверяем некое условие нужно ли повторить и так по кругу.
end

В итоге пришлось изменить на запоминание позиций, и уже потом, после распознования, рисование рамок после всех действий во втором отдельном цикле.
Сам код я не найду но запомнил этот момент навсегда, час потратил наверное на написание десятка разных проверок чтобы понять в чём дело.
Цитата Сообщение от AzAtom Посмотреть сообщение
Переменная объекта и называется полем. Не пойму, в чём проблема. Пока существует экземпляр объекта, его поля тоже на месте.
Так я с этого и начал вчера, и за вчера так никто и не ответил, как будто специально делая вид, что не замечают.
Все 10 условных параллельных потоков могут?! одновременно обратится к указателю на экземпляр класса ведь это не разграничено крит секцией, а если разграничить то не будет многопоточности.
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,495
08.07.2024, 16:13
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Все 10 условных параллельных потоков могут?! одновременно обратится к указателю на экземпляр класса
Могут, если программист гарантирует, что переменная/поле, содержащая адрес объекта будет жить во время работы этих потоков.

Цитата Сообщение от Иван Ежик Посмотреть сообщение
и за вчера так никто и не ответил, как будто специально делая вид, что не замечают.
А это что?
Цитата Сообщение от AzAtom Посмотреть сообщение
А как поток узнаёт адрес объекта? Обычно, он же передаётся заранее, при создании объекта потока. Вот и будет поток хранить адрес объекта в своей области памяти.
То есть, каждый поток будет считывать адрес объекта из своей собственной области памяти.

Хотя, не вижу препятствий для чтения всеми потоками и из одной переменной, при условии, что эта переменная будет жива всё время работы потоков. Читайте на здоровье, тем более, если эта переменная считывается за одно чтение, то вообще нет проблем.

А вот с тем же динамическим массивом уже нужны меры, а то, пока один поток читает данные, другой поток вздумает изменить размер массива и он "переедет" по другому адресу памяти, тогда, первый поток может получить AV.
1
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
08.07.2024, 16:38
Цитата Сообщение от AzAtom Посмотреть сообщение
А это что?
Ну там не ответ про 10 потоков ) и если сделать именно так как указано (назначить адрес при создании потока) то гарантированно два потока не смогут одновременно обратится к адресу экземпляра, ведь создание занимает время, поэтому я и не воспринял как ответ про одновременный доступ.

Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.07.2024, 16:38

Как обратиться к полям класса?
Есть класс в котором в полях заданы некоторые параметры, я создал объект (через указатель), но не знаю как выводить его параметры. То есть...

Доступ к полям класса через переменные другого класса
Уважаемые коллеги! Почему в моделях Аnylogic для упрощения доступа к полям одного класса (класс А) вводится в другой класс (класс В)...

Проблема с обращением к полям класса из другого класса
Приветствую. Работаю с WinForms. У меня есть главная форма DefaultForm, побочные формы TakeOffMoney и InsertMoney, и класс Card. На...

Из одного класса обратиться к свойству progressBar из другого класса (основного окна)
Привет! :) Помогите пожалуйста нубу (мне). У меня есть два класса. Первый (основной), его код: namespace CMS { ///...

Как обратиться к значениям переменной одного класса из метода другого класса
Есть переменная - Холодильник1 класса Freezer Холодильник1 = Freezer() Холодильник2 = Freezer() class Freezer: food...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru