C++11线程、互斥量及条件变量怎么创建

发布时间:2023-03-15 10:06:53 作者:iii
来源:亿速云 阅读:134

C++11线程、互斥量及条件变量怎么创建

目录

  1. 引言
  2. C++11线程库简介
  3. 线程的创建与管理
  4. 互斥量的使用
  5. 条件变量的使用
  6. 线程、互斥量与条件变量的综合应用
  7. 总结

引言

在现代计算机系统中,多线程编程已经成为一种常见的编程范式。通过多线程,程序可以同时执行多个任务,从而提高系统的并发性和响应性。然而,多线程编程也带来了许多挑战,特别是在线程同步和资源共享方面。C++11标准引入了对多线程编程的原生支持,提供了线程、互斥量和条件变量等工具,使得开发者能够更加方便地编写高效、安全的多线程程序。

本文将详细介绍如何在C++11中创建和管理线程、互斥量以及条件变量,并通过实际示例展示它们的综合应用。

C++11线程库简介

C++11标准引入了<thread>头文件,提供了对多线程编程的原生支持。通过这个库,开发者可以创建和管理线程,实现并发执行。此外,C++11还提供了<mutex><condition_variable>头文件,分别用于实现互斥量和条件变量,帮助开发者解决多线程编程中的同步问题。

线程的创建与管理

3.1 创建线程

在C++11中,创建线程非常简单。我们可以通过std::thread类来创建一个新的线程。std::thread的构造函数接受一个可调用对象(如函数、lambda表达式、函数对象等)作为参数,并在新线程中执行该可调用对象。

#include <iostream>
#include <thread>

void hello() {
    std::cout << "Hello, World!" << std::endl;
}

int main() {
    std::thread t(hello);
    t.join();  // 等待线程结束
    return 0;
}

在上面的示例中,我们创建了一个线程t,并在该线程中执行hello函数。join()函数用于等待线程结束。

3.2 线程的启动与终止

线程在创建后会自动启动,执行传递给std::thread构造函数的可调用对象。线程的执行会一直持续,直到可调用对象返回或线程被显式终止。

线程的终止可以通过以下方式实现: - 可调用对象正常返回。 - 调用std::terminate()函数强制终止线程。 - 线程被分离(detach),使其在后台运行,不再与主线程关联。

3.3 线程的分离与连接

线程可以通过detach()函数进行分离,使其在后台运行。分离后的线程将不再与主线程关联,主线程也无法再通过join()等待其结束。

#include <iostream>
#include <thread>

void hello() {
    std::cout << "Hello, World!" << std::endl;
}

int main() {
    std::thread t(hello);
    t.detach();  // 分离线程
    // 主线程继续执行,不再等待t
    return 0;
}

在上面的示例中,线程t被分离,主线程不再等待其结束。

互斥量的使用

4.1 互斥量的基本概念

互斥量(Mutex)是一种用于保护共享资源的同步机制。在多线程环境中,多个线程可能会同时访问共享资源,导致数据竞争和不一致。互斥量通过提供独占访问权,确保同一时间只有一个线程可以访问共享资源。

4.2 互斥量的创建与销毁

在C++11中,互斥量通过std::mutex类实现。我们可以通过以下方式创建和销毁互斥量:

#include <mutex>

std::mutex mtx;  // 创建互斥量

void critical_section() {
    mtx.lock();  // 锁定互斥量
    // 访问共享资源
    mtx.unlock();  // 解锁互斥量
}

在上面的示例中,我们创建了一个互斥量mtx,并在critical_section函数中使用lock()unlock()函数来保护共享资源。

4.3 互斥量的锁定与解锁

互斥量的锁定和解锁是通过lock()unlock()函数实现的。lock()函数用于获取互斥量的所有权,如果互斥量已被其他线程锁定,则当前线程将阻塞,直到互斥量可用。unlock()函数用于释放互斥量的所有权,允许其他线程获取互斥量。

为了避免忘记解锁互斥量,C++11提供了std::lock_guardstd::unique_lock等RI风格的锁管理类,它们在构造时自动锁定互斥量,在析构时自动解锁互斥量。

#include <mutex>

std::mutex mtx;

void critical_section() {
    std::lock_guard<std::mutex> lock(mtx);  // 自动锁定和解锁
    // 访问共享资源
}

在上面的示例中,std::lock_guard在构造时自动锁定mtx,在析构时自动解锁mtx,确保即使在异常情况下也能正确释放互斥量。

4.4 互斥量的类型

C++11提供了多种类型的互斥量,以满足不同的需求:

条件变量的使用

5.1 条件变量的基本概念

条件变量(Condition Variable)是一种用于线程间通信的同步机制。它允许一个线程等待某个条件成立,而另一个线程在条件成立时通知等待的线程。条件变量通常与互斥量一起使用,以确保线程安全。

5.2 条件变量的创建与销毁

在C++11中,条件变量通过std::condition_variable类实现。我们可以通过以下方式创建和销毁条件变量:

#include <condition_variable>

std::condition_variable cv;  // 创建条件变量

5.3 条件变量的等待与通知

条件变量的等待和通知是通过wait()notify_one()notify_all()函数实现的。

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

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void wait_for_ready() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; });  // 等待条件成立
    std::cout << "Ready!" << std::endl;
}

void set_ready() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();  // 通知等待的线程
}

int main() {
    std::thread t1(wait_for_ready);
    std::thread t2(set_ready);
    t1.join();
    t2.join();
    return 0;
}

在上面的示例中,线程t1等待条件ready成立,线程t2在1秒后设置readytrue,并通知t1继续执行。

5.4 条件变量的使用场景

条件变量常用于以下场景: - 生产者-消费者问题:生产者线程生产数据,消费者线程消费数据,条件变量用于通知消费者数据已准备好。 - 读者-写者问题:多个读者线程和写者线程访问共享资源,条件变量用于协调读者和写者的访问顺序。

线程、互斥量与条件变量的综合应用

6.1 生产者-消费者问题

生产者-消费者问题是一个经典的多线程同步问题。生产者线程生产数据并将其放入缓冲区,消费者线程从缓冲区中取出数据并处理。为了确保线程安全,我们需要使用互斥量保护缓冲区,并使用条件变量通知消费者数据已准备好。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> buffer;
const int buffer_size = 10;

void producer() {
    for (int i = 0; i < 20; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, []{ return buffer.size() < buffer_size; });  // 等待缓冲区有空闲
        buffer.push(i);
        std::cout << "Produced: " << i << std::endl;
        lock.unlock();
        cv.notify_all();  // 通知消费者
    }
}

void consumer() {
    for (int i = 0; i < 20; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, []{ return !buffer.empty(); });  // 等待缓冲区有数据
        int data = buffer.front();
        buffer.pop();
        std::cout << "Consumed: " << data << std::endl;
        lock.unlock();
        cv.notify_all();  // 通知生产者
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}

在上面的示例中,生产者线程生产数据并将其放入缓冲区,消费者线程从缓冲区中取出数据并处理。互斥量mtx用于保护缓冲区,条件变量cv用于通知消费者数据已准备好。

6.2 读者-写者问题

读者-写者问题是另一个经典的多线程同步问题。多个读者线程和写者线程访问共享资源,读者线程可以同时访问资源,但写者线程必须独占访问资源。为了确保线程安全,我们需要使用互斥量和条件变量协调读者和写者的访问顺序。

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

std::mutex mtx;
std::condition_variable cv;
int readers = 0;
bool writing = false;

void reader() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return !writing; });  // 等待没有写者
    ++readers;
    lock.unlock();

    // 读取共享资源
    std::cout << "Reading..." << std::endl;

    lock.lock();
    --readers;
    if (readers == 0) {
        cv.notify_all();  // 通知写者
    }
    lock.unlock();
}

void writer() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return readers == 0 && !writing; });  // 等待没有读者和写者
    writing = true;
    lock.unlock();

    // 写入共享资源
    std::cout << "Writing..." << std::endl;

    lock.lock();
    writing = false;
    cv.notify_all();  // 通知读者和写者
    lock.unlock();
}

int main() {
    std::thread t1(reader);
    std::thread t2(writer);
    std::thread t3(reader);
    t1.join();
    t2.join();
    t3.join();
    return 0;
}

在上面的示例中,读者线程和写者线程访问共享资源。互斥量mtx用于保护共享资源,条件变量cv用于协调读者和写者的访问顺序。

总结

C++11标准引入了对多线程编程的原生支持,提供了线程、互斥量和条件变量等工具,使得开发者能够更加方便地编写高效、安全的多线程程序。通过本文的介绍,我们了解了如何在C++11中创建和管理线程、互斥量以及条件变量,并通过实际示例展示了它们的综合应用。

多线程编程虽然强大,但也带来了许多挑战,特别是在线程同步和资源共享方面。因此,在实际开发中,我们需要谨慎使用多线程,确保程序的正确性和性能。希望本文能够帮助读者更好地理解和应用C++11中的多线程编程技术。

推荐阅读:
  1. HTML中如何通过PHP调用C++
  2. python3 整数类型PyLongObject 和PyObject源码分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:python3中SQLMap如何安装

下一篇:Python如何实现对中文文本分段分句

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》