Как запустить bar() внутри foo(), если bar() и foo() взаимоисключающие

У меня есть две функции, скажем, foo() и bar(), я хочу, чтобы они были взаимоисключающими, то есть полностью блокировали работу foo(), когда работает bar(), или полностью блокировали работу bar(), когда foo() работает для безопасности потоков.

Тем не менее, я могу вызвать bar() внутри foo(), то есть когда foo() вызывает bar() внутри foo(), пусть выполняется bar(), но никакие другие потоки не вызывают bar().

Является ли это возможным? Если да, можете ли вы дать общую идею, пожалуйста?

Пытался использовать один или несколько мьютексов в C, легко сделать две функции взаимоисключающими, но тогда я не могу вызвать bar() внутри foo(), они войдут в тупик.

Я не могу просто разблокировать мьютекс прямо перед вызовом bar() внутри foo(), потому что я не могу гарантировать, что следующий запущенный bar() будет вызван внутри foo().

Я ищу решение, при котором foo будет блокировать bar, а bar будет блокировать foo, если они будут работать в разных потоках. но когда foo вызывает bar внутри своего тела (тот же поток), пусть bar работает.

Спасибо

However, I may call bar() inside foo(), this is, when foo() calls bar() inside foo(), let bar() to run, but not any other threads call bar(). Никогда не пытайтесь объяснить код, возможно, включите пример кода.
kiran Biradar 21.05.2019 15:35

Моя идея состоит в том, чтобы использовать идентификатор потока в качестве базы и мьютексировать этот идентификатор, поэтому T1 вызывает Foo, устанавливает идентификатор потока и продолжает, T2 вызывает Bar, блокируется (другой идентификатор потока). T1 вызывает Bar , может с того же идентификатора потока. Это очень-очень общая идея.

Gar 21.05.2019 15:41

Показать код для нас

klutt 21.05.2019 15:48

@Gar Если я хорошо понял вашу идею, единственный способ получить доступ к bar() - это вызвать его из foo(), это не очень хорошо:/ и что произойдет, если один поток войдет в foo(), а другой - в bar(), и они оба wan 't для доступа к другой функции, у вас будет тупик.

desmaxi 21.05.2019 15:56

Вовсе нет, если bar не вызывается (ни foo), любой из них может быть вызван, поскольку сохраненный threadID равен null , как только один из них будет вызван, threadID будет заполнен и остановит вход любого другого потока.

Gar 21.05.2019 15:59

@Gar Хорошо понял твою идею, теперь я понял. Вроде должно работать :)

desmaxi 21.05.2019 16:03

Я думаю, вам следует пересмотреть то, о чем вы спрашиваете. Для безопасности потоков вас действительно интересует, какие данные будут изменены; вам не нужно/не следует заботиться о том, какие функции выполняются (кроме случаев, когда они изменяют общие данные). Перевернув его, это может сделать вашу задачу более ясной. Кажется вероятным, что рекурсивный мьютекс легко решит вашу проблему, но опять же, это требует тщательного рассмотрения того, что на самом деле охраняется.

Gil Hamilton 21.05.2019 19:03

Спасибо всем

B.Hong 22.05.2019 01:41
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Самый простой способ сделать это — переместить основную реализацию bar() и foo() в отдельные вспомогательные функции bar_unlocked() и foo_unlocked(), а затем реализовать bar() и foo() как:

type foo(args)
{
    type result;

    pthread_mutex_lock(&barfoo_lock);
    result = foo_unlocked(args);
    pthread_mutex_unlock(&barfoo_lock);

    return result;
}

type bar(args)
{
    type result;

    pthread_mutex_lock(&barfoo_lock);
    result = bar_unlocked(args);
    pthread_mutex_unlock(&barfoo_lock);

    return result;
}

Вы можете безопасно вызывать bar_unlocked() из реализации foo_unlocked().

Большое спасибо, это именно то, что мне нужно.

B.Hong 22.05.2019 01:39

Другой способ сделать это — использовать так называемый «реентерабельный» или «рекурсивный» объект мьютекса/блокировки.

https://en.cppreference.com/w/cpp/thread/recursive_mutex

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

Рекурсивные блокировки - это функция, которая появляется во многих различных многопоточных библиотеках, но я не знаю о библиотеке pthreads, поэтому, возможно, ответ @caf будет для вас лучшим выбором.

Рекурсивные мьютексы могут быть созданы в pthreads путем инициализации мьютекса с помощью объекта mutexattr, для которого тип мьютекса установлен на PTHREAD_MUTEX_RECURSIVE с pthread_mutexattr_settype(). Однако, как правило, проще анализировать поведение программы, если не полагаться на подобные вещи.

caf 22.05.2019 02:27

Другие вопросы по теме