C++ 多线程

目录

目录

多线程的创建与执行

多线程的互斥

1. 创建一个mutex对象,lock(),unlock()

2. 借助lock_guard

3. unique_lock: lock_guard的升级加强版


多线程的创建与执行

1. C++借助标准库来实现。将函数名放入线程中即可,如果函数有参数,一同放入。

2. 执行方式有两种

join方式:当启动的线程执行完毕后,才会继续运行下面的代码

detach方式:不必等待。

void func(int n, char c) {
   
    for (int i = 0; i < n; i++) {
        cout << c;
    }
    cout << endl;
}

void test() {
    int n = 10;
    char c = '*';
    thread thread1(func, n, c);    //创建线程
    
    c = '%';
    thread thread2(func, n, c);

    thread1.join();          //等待线程1执行结束才会执行线程2
    thread2.join();
}

多线程的互斥

C++引入了一个标准库帮助实现简单的线程互斥。其中有3种方法。

1. 创建一个mutex对象,lock(),unlock()

该对象对临界区上锁解锁,实现只有一个线程访问临界区。

#include
#include
using namespace std;

mutex mtx;                //创建一个mutex对象mtx
void func(int n, char c) {
    mtx.lock();             //对临界区上锁

    for (int i = 0; i < n; i++) {
        cout << c;
    }
    cout << endl;

    mtx.unlock();   //解锁
}

void test() {
    int n = 10;
    char c = '*';
    thread thread1(func, n, c);    //创建线程
    
    c = '%';
    thread thread2(func, n, c);

    thread1.join();          //等待线程执行结束
    thread2.join();
}

2. 借助lock_guard

创建一个lock_guard对象,他获取提供给他的互斥锁的所有权。

lock_guard:创建即上锁,超出作用域自动解锁;不能中途解锁;不能复制(因为它的赋值拷贝设置为私有成员函数了)。

优点:防止忘记解锁,造成死锁。

缺点:整个作用域加锁,锁的粒度太大。可以自己再加一个大括号来控制作用域。

#include
#include

int temp = 0;
mutex temp_guard;  //用来保护temp
void func2(){
    //保证当当前进程访问调用函数fun2时,其他的会被阻塞

    //lock_guard在出作用域时会自动解锁
    //为访问公共资源 上锁
    const std::lock_guardlock(temp_guard);  
    temp++;
}

void test02() {
    thread thread1(func2);
    thread thread2(func2);
    thread1.join();
    thread2.join();
}

3. unique_lock: lock_guard的升级加强版

unique_lock的特点:

1. 创建时可以不加锁(参数std::defer_lock),默认是创建加锁的。

2. 可以随时加锁解锁。lock(),unlock()

3. 不手动解锁的话,超出作用域就自动解锁了。

4. 不能复制,可以移动

struct Box   //结构体中有一个数字 和mutex对象
{
    std::mutex mtx;   //有一个互斥量
    int num;
    Box(int n):num(n){}
};

void transfer(Box& from, Box& to, int n) {

    //先创建锁,稍后加锁
    std::unique_locklock1(from.mtx, std::defer_lock);
    std::unique_locklock2(to.mtx, std::defer_lock);

    //同时对他们加锁
    lock(lock1, lock2);

    from.num -= n;
    to.num += n;

}

void test03() {
    Box from(100);
    Box to(30);

    std::thread thread1(transfer, std::ref(from), std::ref(to), 10);
    std::thread thread2(transfer, std::ref(from), std::ref(to), 20);
    thread1.join();
    thread2.join();

    cout << from.num << " " << to.num << endl;
    cout << from.num << " " << to.num << endl;
}

你可能感兴趣的:(c++,多线程)