线程同步之互斥锁

yubo-guan / 2024-01-19 / 原文

目录
  • 如何使用Mutex中的lock与unlock
  • try_lock、try_lock_for和try_lock_until
    • try_lock
    • try_lock_for
    • try_lock_until


如何使用Mutex中的lock与unlock

在C++11中,您可以使用std::mutex中的lockunlock函数来实现线程同步。lock函数用于锁定互斥量,而unlock函数用于解锁互斥量。

下面是一个简单的示例,演示了如何在C++11中使用std::mutexlockunlock函数:

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

std::mutex mtx; // 用于临界区的互斥量

void print_thread_id(int id) {
    // 临界区(通过锁定mtx来实现对std::cout的独占访问):
    mtx.lock();
    std::cout << "thread #" << id << '\n';
    mtx.unlock();
}

int main() {
    std::thread threads[10]; // 创建10个线程
    for (int i = 0; i < 10; ++i) {
        threads[i] = std::thread(print_thread_id, i + 1);
    }
    for (auto &th : threads) {
        th.join();
    }
    return 0;
}
/*
thread #1
thread #5
thread #3
thread #4
thread #7
thread #8
thread #9
thread #10
thread #2
thread #6

*/

try_lock、try_lock_for和try_lock_until

在C++11中,可以使用std::mutextry_locktry_lock_fortry_lock_until方法来尝试获取互斥锁。这些方法允许线程尝试获取锁,如果获取成功则返回true,否则返回false

以下是使用这些方法的示例代码:

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

std::mutex mtx; // 用于临界区的互斥量

void job() {
    std::cout << "begin thread # " << std::this_thread::get_id() << std::endl;
    if (mtx.try_lock()) {
        std::cout << std::this_thread::get_id() << " Lock acquired" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        mtx.unlock();
    } else {
        std::cout << std::this_thread::get_id() << " Failed to acquired lock" << std::endl;
    }
    std::cout << "end thread # " << std::this_thread::get_id() << std::endl;;
}

int main() {
    std::thread t1(job);
    std::thread t2(job);

    t1.join();
    t2.join();
    
    return 0;
}

/*
begin thread # 139732969322176
139732969322176 Lock acquired
begin thread # 139732960929472
139732960929472 Failed to acquired lock
end thread # 139732960929472
end thread # 139732969322176
*/

在上面的示例中,try_lock方法尝试获取互斥锁,如果获取成功则输出"Lock acquired",否则输出"Failed to acquire lock"。

另外,try_lock_fortry_lock_until方法也可以用类似的方式来使用,它们允许线程在一定时间内尝试获取锁,超时则返回false

Mutex是一种用于多线程编程的同步原语,用于保护共享资源,以防止多个线程同时访问。在C++中,我们可以使用std::mutex来实现互斥锁。std::mutex提供了几种尝试加锁的方法,包括try_locktry_lock_fortry_lock_until。下面我将分别介绍这三种方法的用法和作用。

try_lock

try_lockstd::mutex类的成员函数,用于尝试对互斥锁进行加锁。如果当前没有其他线程占用锁,try_lock会立即对锁进行加锁,并返回true;如果锁已经被其他线程占用,try_lock会立即返回false,而不会阻塞当前线程。

#include <mutex>

std::mutex mtx;

void example_function() {
    if (mtx.try_lock()) {
        // 成功获得锁
        // 执行一些操作
        mtx.unlock();  // 记得在操作结束后释放锁
    } else {
        // 未能获得锁
    }
}

try_lock_for

try_lock_forstd::mutex类的成员函数,用于尝试在指定的时间段内对互斥锁进行加锁。如果在指定时间内获得了锁,函数返回true;如果在指定时间内未获得锁,函数返回false

#include <mutex>
#include <chrono>

std::mutex mtx;

void example_function() {
    if (mtx.try_lock_for(std::chrono::milliseconds(100))) {
        // 成功获得锁
        // 执行一些操作
        mtx.unlock();  // 记得在操作结束后释放锁
    } else {
        // 未能在100毫秒内获得锁
    }
}

try_lock_until

try_lock_untilstd::mutex类的成员函数,用于尝试在指定的时间点之前对互斥锁进行加锁。如果在指定时间点之前获得了锁,函数返回true;如果在指定时间点之前未获得锁,函数返回false

#include <mutex>
#include <chrono>

std::mutex mtx;

void example_function() {
    auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(1000);
    if (mtx.try_lock_until(timeout)) {
        // 成功获得锁
        // 执行一些操作
        mtx.unlock();  // 记得在操作结束后释放锁
    } else {
        // 未能在指定时间点之前获得锁
    }
}

这些方法可以帮助我们在多线程编程中更灵活地管理互斥锁,避免线程阻塞和死锁的问题。