Какова область действия объекта std::mutex?

#c #multithreading

Вопрос:

Вот пример кода:

 #include <iostream>
#include <thread>
#include <mutex>

int value = 0;

void criticalSection(int changeValue)
{
    std::mutex mtx;
    std::unique_lock<std::mutex> uniqueLock(mtx);
    value = changeValue;
    std::cout << value << std::endl;
    uniqueLock.unlock();
    uniqueLock.lock();
      value;
    std::cout << value << std::endl;
}

int main(int argc, char **argv)
{
    std::thread t1(criticalSection, 1), t2(criticalSection, 2);
    t1.join();
    t2.join();

    return 0;
}
 

Мой вопрос: какова область применения mtx в приведенном выше коде? Будет ли каждый поток создавать mtx в этом потоке? Есть ли какая-то разница, если я укажу mtx в качестве глобальной переменной вместо локальной переменной?

Я только начал изучать многопоточность на C . Большое вам спасибо за вашу помощь.

Комментарии:

1. Наличие функции void foo () {int bar = 0; } , какова область действия bar переменной и будет ли создаваться новая bar переменная при каждом вызове foo функции? Ответ тот же, что и у std::mutex меня .

2.Область действия a std::mutex такая же, как и для любого другого объекта. «Будет ли каждый поток создавать mtx в этом потоке?«- Да, если ты не сделаешь это static примером

3. Это та же область, что и если int a; бы была объявлена вместо нее.

4. Правило простое: область действия мьютекса должна соответствовать области действия защищаемых данных.

5. Большое вам всем спасибо. Это мой первый вопрос, и я получил так много полезных ответов. Я надеюсь, что у вас у всех будет хороший день!

Ответ №1:

Для мьютексов не существует специальных правил определения области действия. Их область применения заканчивается на следующем } . В вашем коде каждый вызов criticalSection создает новый mutex экземпляр. Следовательно, мьютекс невозможно использовать для синхронизации двух потоков. Для этого обоим потокам потребуется использовать один и тот же мьютекс.

Вы можете передать ссылку на мьютекс функции:

 #include <iostream>
#include <thread>
#include <mutex>

int value = 0;

void criticalSection(int changeValue,std::mutexamp; mtx)
{
    std::unique_lock<std::mutex> uniqueLock(mtx);
    //...
}

int main(int argc, char **argv)
{
    std::mutex mtx;
    std::thread t1(criticalSection, 1,std::ref(mtx)), t2(criticalSection, 2,std::ref(mtx));
    t1.join();
    t2.join();

    return 0;
}
 

В качестве альтернативы вы можете использовать a std::atomic<int> value; и удалить мьютекс, когда value это единственное общее состояние.

Комментарии:

1. Спасибо. После прочтения вашего ответа мой вопрос решен. Хорошего дня!

Ответ №2:

mutex Тип не изменяет правила C в отношении того, как работают переменные и объекты.

Если вы объявите static непеременную в стеке, каждый вызов этой функции создаст свою собственную версию этой переменной. Независимо от того, о какой теме идет речь. Все это отдельные и отличные друг от друга объекты.

Когда вы блокируете a mutex , вы блокируете этот объект. Другие объекты того же типа не связаны с этой блокировкой.

Чтобы сделать mutex что-то полезное, обе части кода, пытающиеся заблокировать его, должны блокировать один и тот же объект. То, как вы это сделаете, в конечном счете зависит от ваших потребностей.

Комментарии:

1. Ну, это немного волшебно, просто никак не связано с областью применения

2. Большое вам спасибо за вашу помощь. Теперь я знаю, что мне нужно сделать объект мьютекса статичным.