Spec-Zone.ru › C++

std::shared_mutex::lock_shared

void lock_shared();
(начиная с C++17)

Получает совместное владение мьютексом. Если другой поток владеет мьютексом эксклюзивно, вызов lock_shared заблокирует выполнение до тех пор, пока не удастся получить совместное владение.

Если lock_shared вызывается потоком, который уже владеет mutex в любом режиме (эксклюзивном или совместном), поведение не определено.

Если мьютекс в совместном режиме уже заблокирован числом владельцев, превышающим установленный реализацией максимум, lock_shared блокирует выполнение до уменьшения числа владельцев. Гарантируется, что максимальное число владельцев составляет не менее 10000.

Предшествующая операция unlock() над тем же мьютексом синхронизируется с (как определено в std::memory_order) этой операцией.

Параметры

(нет)

Возвращаемое значение

(нет)

Исключения

При возникновении ошибок выбрасывает std::system_error, включая ошибки базовой операционной системы, которые не позволили бы lock соответствовать спецификации. В случае выбрасывания любого исключения мьютекс не блокируется.

Примечания

lock_shared() обычно не вызывается напрямую: для управления совместной блокировкой используется std::shared_lock.

Пример

#include <chrono>
#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <syncstream>
#include <thread>
#include <vector>

std::mutex stream_mutx;
void print(auto v)
{
    std::unique_lock<std::mutex> lock(stream_mutx);
    std::cout << std::this_thread::get_id() << " saw: ";
    for (auto e : v)
        std::cout << e << ' ';
    std::cout << '\n';
}

int main()
{
    using namespace std::chrono_literals;
    constexpr int N_READERS = 5;
    constexpr int LAST = -999;

    std::shared_mutex smtx;
    int product = 0;

    auto writer = [&smtx, &product](int start, int end)
    {
        for (int i = start; i < end; ++i)
        {
            auto data = i;            
            {
                std::unique_lock<std::shared_mutex> lock(smtx);
                product = data;
            } 
            std::this_thread::sleep_for(3ms);
        }

        smtx.lock(); // lock manually
        product = LAST;
        smtx.unlock();
    };

    auto reader = [&smtx, &product]()
    {
        int data = 0;
        std::vector<int> seen;
        do
        {
            {
                smtx.lock_shared(); // better to use: std::shared_lock lock(smtx);
                data = product;
                smtx.unlock_shared();
            }                                   

            seen.push_back(data);
            std::this_thread::sleep_for(2ms);
        }
        while (data != LAST);

        print(seen);
    };

    std::vector<std::thread> threads;
    threads.emplace_back(writer, 1, 13);
    threads.emplace_back(writer, 42, 52);

    for (int i = 0; i < N_READERS; ++i)
        threads.emplace_back(reader);

    for (auto&& t : threads)
        t.join();
}

Возможный вывод:

127755840 saw: 43 3 3 4 46 5 6 7 7 8 9 51 10 11 11 12 -999
144541248 saw: 2 44 3 4 46 5 6 7 7 8 9 51 10 11 11 12 -999
110970432 saw: 42 2 3 45 4 5 47 6 7 8 8 9 10 11 11 12 -999
119363136 saw: 42 2 3 4 46 5 6 7 7 8 9 9 10 11 11 12 12 -999
136148544 saw: 2 44 3 4 46 5 6 48 7 8 9 51 10 11 11 12 12 -999

См. также

lock
блокирует мьютекс; если мьютекс недоступен, ожидание блокирует выполнение
(открытая функция-член)
try_lock_shared
пытается получить совместное владение мьютексом; возвращает управление, если мьютекс недоступен
(открытая функция-член)
unlock_shared
разблокирует мьютекс (совместное владение)
(открытая функция-член)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/thread/shared_mutex/lock_shared

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API