общие функции в многопоточном программировании

Тема в разделе "WASM.BEGINNERS", создана пользователем beginner, 17 мар 2008.

  1. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    Изучаю многопоточное программирование, с событиями, мьютексами вроде разобрался.
    Такой вопрос: Что будет, если два и более потока вызовут функцию, которая находится вне потоков, она как бы глобальная. Например, strlen() или какую нибудь другую функцию пользователя.
    И что будет, если в ней будут использоваться какие то свои локальные переменные? Не будет ли какой-то пакости?
     
  2. steelfactor

    steelfactor New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    501
  3. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Ничего не будет. У кажд. потока свой стек. лишь бы глобальными не пользовалась, а то без синххронизации никак.
     
  4. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    asmfan
    это точно? Известно что потоки используют единое адресное пространство. К глобальным переменным я обращаюсь через мьютексы. А как дело обстоит с глобальными функциями? функции, которые имеют один и тот же адрес. Как происходит работа в ней, когда ее вызывают сразу несколько потоков?
     
  5. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    beginner
    В Visual Studio "зачем-то" две версии библиотек - просто и мультипоточная.
    Соответственно и пользовательские функции должны быть двух видов,
    если необходимо.
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    beginner
    Синхронизация нужна только для изменяемых данных. Функция это просто кусок неизменяемой памяти, в котором записан код. Если в функции не используются глобальные переменные, то разные ядра\процы могут параллельно считывать из памяти и исполнять один и тот же кусок кода, т.к. у каждого потока своя собственная область стека. Т.е. код функции один и тот же, а адреса локальных переменных, копий регистров (push\pop) и адреса возврата у каждого потока свои
     
  7. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Функция сама по себе -- это просто набор байтов в памяти. Вне потока она не исполняется, т.е. как бы не существует :) Так что "внепоточных функций" быть не может.

    Проблема в другом: если некая функция может быть вызвана повторно до того, как её первое выполнение полностью завершится, она должна быть повторно-входимой (реентерабельной). Чтобы она удовлетворяла этому требованию, надо соблюдать несколько простых правил, из которых важнейшие -- не изменять собственный код (при программировании на ЯВУ это всегда так) и использовать на запись только локальные переменные (в том числе значения параметров, переданных ей через адреса), но ни в коем случае не глобальные переменные.

    Синхронизация же к одновременному выполнению одной и той же функции прямого отношения не имеет.
     
  8. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    leo
    ОООООО, я подобный ответ хотел услышать!
    т.е. получается, когда поток вызывает внешнюю общую функцию, для него даже не важно что она общая. Правильно?
    Забегая наперед, хочу еще спросить:
    Что будет, если в этой глобальной функции будет обращение к какой то глобальной переменной, ессно через средства синхронизации, мютекс или событие - не столь важно. Другие потоки, которые вызовут эту функцию, когда дойдут до обращения к этой глобальной переменной - приостановятся и будут ждать пока переменная освободится для использования? Если несколько потоков обратятся - будет ли создана какая то очередь по доступу к этой переменной? Типа поток 1 первый обратился к переменой - он и первый получит доступ, поток 2 - вторым обратился и второй получит доступ. Так ли это на самом деле?
    Заранее спасибо тебе и всем людям, которые помогают в этом нелегком деле - программировании :)

    valterg
    Я почему то всю жизнь думал, что в студии две версии библиотек: релиз и дебаг...

    Блин я не успеваю формулировать новые вопросы, как уже практически отвечают на них
    Очень классный форум, ответ на вопрос можно получить практически сразу, что очень радует. И не просто ответ, а очень квалифицированный ответ! I'm happy!
    SII
    Получается что если нельзя использовать глобальную переменную в таких функциях, то можно поступить следующим образом: сохранить эту глобальную переменную в какую нибудь временную, и уже ее передать некой функции для обработки. А по возращении результата - сохранить ее обратно в глобальную, используя средства синхронизации.
    Мне кажется в этом случае проблем с глобальными переменными вообще не будет, но хочется узнать что получится, если использовать метод, который я выше описал?
    Спасибо.
     
  9. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    Зависит от средств синхронизации
    4 как минимум: single-thread debug, single-thread release, multi-thread debug, multi-thread release
     
  10. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    самый лучший способ обеспечить реентерабельность - использовать per-cpu/TLS/атомарные данные, а не синхронизацию
     
  11. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    если размер переменной будет больше максимального размера операнда какой-либо атомарной инструкции, при сохранении тоже понадобится синхронизация
     
  12. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    rei3er
    про атомарные данные вообще в первый раз слышу...
    при сохранении ессно будет синхронизация... я просто не дописал, спасибо :)
     
  13. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    не так выразился
    данные, которые могут целиком использоваться в качестве операндов атомарных инструкций
     
  14. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    beginner
    rei3er
    Уж сразу бы пояснили про атомарные инструкции ;)

    В общем, такие инструкции, которые, обращаясь к данным, полностью блокируют занимаемую ими область памяти на всё время доступа. Всегда такой является инструкция XCHG -- пока она считывает из памяти старое значение некоей переменной и записывает новое, доступ к памяти блокирован, поэтому есть гарантия, что никакой потусторонний поток, даже выполняемый на другом процессоре многопроцессорной системы, вклиниться в этот процесс не сможет. Ряд других инструкций могут быть сделаны атомарными с помощью префикса LOCK. Подробно всё расписано в интеловских мануалах.

    Однако на ЯВУ надо разбираться, как этот самый атомарный доступ выполнять. Лично я Си практически не использую, поэтому понятия не имею, ну а на Паскале (Дельфи) я привык все такие вещи делать с помощью ассемблерных вставок.

    Что же касается синхронизации, то всегда следует помнить о возможности возникновения взаимоблокировки. Если процесс 1 захватил блокировку А и пытается захватить блокировку Б, а процесс 2 захватил блокировку Б и пытается захватить блокировку А, они повисли намертво -- это состояние, именуемое дедлоком (deadlock). Чтобы такого не происходило, необходимо предусмотреть определённую очерёдность захвата блокировок -- это не слишком сложно (я б даже сказал, совсем не сложно), но к этому нужно привыкнуть :)
     
  15. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Использовать функции АПИ InterlockedXXX
     
  16. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    beginner
    Тебе стоит прочитать Джеффри РИХТЕР "Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows" Там про синхронизацию(и про много что ещё) подробно расписано.
     
  17. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    инструкция, обеспечивающая целостность своих операндов (названных "атомарные данные"), которая выполняется без выделения тактов процессора другим инструкциям.

    P.S. это определение можно расширить и спроецировать на синхронизацию, где для создания "атомарных данных" вводятся дополнительные переменные.
    т.е. "безопасный поток" - поток, обеспечивающий целостность своих данных при переключении контекста.
     
  18. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    тогда уж для полноты картины стоит добавить, что чтение/запись (mov) 1 байта всегда атомарны
    также атомарны чтение/запись 2, 4, 8 (на 64-х разрядных системах) байт по адресам, кратным соответственно 2-ум, 4-м и 8-ми
    в GCC есть набор built-in функций типа
    __sync_bool_compare_and_swap()
    __sync_fetch_and_add()
    и т. д
     
  19. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    asd
    Спасибо, уже скачал, осваиваю!!!

    Увы атомарные инструкции наврядли будут доступны, так как общими переменными являются структуры.
    Делаю только через синхронизацию.

    Счас пока разбираюсь, вопросов много, но все они решаемы после прочтения статей/книг.
    Главное что можно запустить одну и ту же функцию из разных потоков - это то что мне нужно было!!