c++并发编程(一)

本文介绍了在C++中使用互斥锁(mutex)来避免竞态条件(racecondition),特别是关键区域(criticalsection)的概念,以及如何通过`lock()`和`unlock()`函数保护共享资源。通过示例展示了如何在多线程环境中创建和同步线程以确保数据一致性。
摘要由CSDN通过智能技术生成

0.mutex in c++

//topic:mutex in c++ threading | why us mutex | what is race condition and how to solve it? |what is critial section
//mutex: mutual ecxlusion

//RACE CONDITION 竞争条件  意味着至少有两个操作数或多于两个,除非修改数据,否则不存在竞争
//0 race condition is a situation where two or more threads/process happend to chage a common data at the same time
//1.if there is a race condition then we have to protect it and the protected setion is called critical section/region

//mutex:
//0. mutex is used to avoid race condition
//1 .wu use lock() ,unlock() on mutex to avoid race condition
/*
对数据的操作  1.load 2.change 3 save


*/
#include <iostream>
#include <thread>
#include <mutex>

int count = 0;
std::mutex m;

// 关键区域critical section 出现关键区域可以使用互斥体mutex
// 访问关键部分前,必须锁定互斥锁,完成后需要解锁它,以便如果有任何线程等待这个锁,该线程将被解锁并开始使用这个锁
// 能保证两个线程不会同时在这个地方工作,保证没有race condition
void addcount() {
    m.lock();
    for(int i = 0; i < 10000; i++) {
        count ++;
    }
    m.unlock();
}
int main() {
    std::thread thread1(addcount);
    std::thread thread2(addcount);
    
    thread1.join();
    thread2.join();
    std::cout << "count: " << count << std::endl;
    return 0;
}

1. multithreading in c++

/*
topic: introduction to thread in c++(c++ 11)

qustions
1.what do you understand by thread and give one example in C++

answer:
0. in every application there is a default thread which is main
1. a thread is also known as lightweight process. Idea is achieve parallelism by dividing a process into multipule threads.
    for example:
        the browser has multiple tabs that can be different threads.
        MS Word must be using multiple threads, one thread to format the text, another thread to process inputs(spell checker)
        visual studio code editor would be using threading for auto completing the code.(Intellicence)

ways to create threads in c++11
1. function pointers
2.lambda functions
3.functors
4.member funcitons
5.static member functions

Requirement
find the addition of all odd number from 1 to 1900000000 and all even number from 1 to 1900000000

*/

#include <iostream>
#include <thread>
#include <chrono>
#include <functional>

typedef unsigned long long ull;

void addEvenSum(int start, int end, ull& sum_even) {
    for (ull i = start; i < end; i++) {
        if (i % 2 == 0) {
            sum_even += i;
        }
    }
}
void addOddSum(int start, int end, ull& sum_odd) {
    for (ull i = start; i < end; i++) {
        if (i % 2 == 1) {
            sum_odd += i;
        }
    }
}

int main() {
    int start = 0;
    int end = 2000000000;
    ull sum_even = 0, sum_odd = 0;
    auto startTime = std::chrono::high_resolution_clock::now();
    std::thread t1(addEvenSum, start, end, std::ref(sum_even));
    std::thread t2(addOddSum, start, end, std::ref(sum_odd));

    t1.join();
    t2.join();

    // addOddSum(start, end, sum_odd);
    // addEvenSum(start, end, sum_even);

    auto stopTime = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stopTime - startTime);
    std::cout << "sum_odd:" << sum_odd << std::endl;
    std::cout << "sum_even:" << sum_even << std::endl;

    std::cout << "duration time :" << static_cast<ull>(duration.count()) << "millsec" << std::endl;

}

2.How to create threads

/*
topic: types of thread creation in c++ 11
there are 5 different types we can create threads in c++11 using callable objects;

note:
if we create multiple threads at the same time it doesn't guarantee which one will start first.

// 1.function pointer 函数指针
// this ts very basic form of thread creation
//2.lambda function
// we can directly inject lambda at thread creation time
//3. functor (function Object)
//特定函数将被视为可调用对象
// 4. Non_static member function




*/
#include <iostream>
#include <thread>
// 1.function pointer 函数指针
// this ts very basic form of thread creation
void function(int x) {
    while(x-- > 0) {
        std::cout <<"1:" << x << std::endl;
    }
}

/*
Lambda表达式的结构
Lambda表达式的一般形式如下:


[ capture clause ] ( parameters ) -> return_type {
    function_body
}
在你提供的例子中,lambda表达式具体分解如下:

[ capture clause ]:这个lambda没有捕获任何外部变量,因此捕获子句为空。
( parameters ):参数列表中定义了一个名为x的int类型参数。
-> return_type:这个lambda没有显式指定返回类型。当没有指定返回类型且函数体中包含直接返回语句时,返回类型可以自动推断。在这个例子中,lambda函数没有返回任何值(隐式返回void)。
{ function_body }:函数体包含一个循环,循环中递减x并在每次迭代中打印x的值,直到x减至0以下。

Lambda表达式是C++中一个强大的功能,它们允许快速定义小的、用完即丢的函数对象,非常适合作为回调、临时函数或在需要简单函数对象的任何场合使用。
*/
// auto function2 = [](int x){
//     while (x -- > 0) {
//         std::cout << "2: " << x << std::endl;
//     }
// };


class Base{
public:
//3. functor (function Object)
//特定函数将被视为可调用对象
    void operator() (int x) {
        while (x-- > 0) {
            std::cout << "3:" << x << std::endl;
        }
    }
// 4. Non_static member function
    void run(int x) {
        while(x-- > 0) {
            std::cout << "4:" << x << std::endl;
        }
    }
// 5.static member function
    static void run2(int x) {
        while(x-- > 0) {
            std::cout << "5:" << x << std::endl;
        }
    }

    
};



int main() {
    int x = 30;
    std::thread t1(function, x);
    //2.lambda function
    // we can directly inject lambda at thread creation time
    std::thread t2([](int x){
    while (x -- > 0) {
        std::cout << "2: " << x << std::endl;
        }
    }, x);
    std::thread t3((Base()), x);
    Base b;
    std::thread t4(&Base::run, &b, x);
    //调用静态成员函数,不需要任何对象,可以直接用函数地址
    std::thread t5(&Base::run2, x);


    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();

    return 0;
}

3.join and detach in c++

/*
topic: use of join(), detach(), and joinable() in thread in c++ (c++ 11)

join notes
0.once a thread is started we wait for this thread to finish by calling join() function on thread object.
1.double join will result into program termination.
2.if needed we should check thread is joinable before joining.(using joinable() function)

detach notes
0. this is used to detach newly created thread from parent thread.
1.always check before detaching a thread that it is joinable othrewise we may end up double detaching and double detach()
will result into program termination.
2.if we have detached thread and mian function is returning then the detached thread execetion suspended.

notes:
either join() or detach() should be called on thread object,otherwise during thread object's destructor it will terminate the 
program. because inside destructor it checks if thread is still joinable? if yes then it terminates the program.
如果要创建线程,必须编写join()或detach()
*/

#include <iostream>
#include <thread>
#include <chrono>

void run(int num) {
    while (num --> 0) {
        std::cout << num << "runthread:" << std::endl;
    }
    std::this_thread::sleep_for(std::chrono::seconds(3));
}

int main() {
    std::thread t1(run, 10);
    std::cout << "main():" << std::endl;
    // t1.join();
    //一个好的习惯是join()前先判断joinable()
    // if (t1.joinable())
    //     t1.join();

    if (t1.joinable())
        t1.detach();
    for (int i = 0; i< 10000; i++) {
        if (i % 100 == 0) {
            std::cout<< i << std::endl;
        }
    }
    std::cout << "main() after" << std::endl;
    return 0;
}

学习链接https://www.youtube.com/watch?v=q3-5sDe6lzg

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值