你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

树莓派-C++之多线程(二)

2021/12/18 0:20:56

2021SC@SDUSC

我们看完线程并发:

void thread01()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 01 is working !" << endl;
        Sleep(100);
    }
}
void thread02()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 02 is working !" << endl;
        Sleep(200);
    }
}
  
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.join();
    task02.join();
  
    for (int i = 0; i < 5; i++)
    {
        cout << "Main thread is working !" << endl;
        Sleep(200);
    }
    system("pause");
}

join方式,等待启动的线程完成,才会继续往下执行。假如前面的代码使用这种方式。这是其中一个线程等待另一个线程的完成,之后才会向下进行。

再看另一种情况:

void thread01()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 01 is working !" << endl;
        Sleep(100);
    }
}
void thread02()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 02 is working !" << endl;
        Sleep(200);
    }
}
  
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.detach();
    task02.detach();
  
    for (int i = 0; i < 5; i++)
    {
        cout << "Main thread is working !" << endl;
        Sleep(200);
    }
    system("pause");
}

detach方式,启动的线程自主在后台运行,当前的代码继续往下执行,不等待新线程结束。这种情况下,两个线程互不干扰。

转移线程的所有权:

线程是可移动的,可以通过move来改变线程的所有权,灵活的决定线程在什么时候join或者detach。

thread t1(f1);
thread t2(move(t1));

将线程从t1转移给t2,这时候t1就不再拥有线程的所有权,调用t1.joint1.detach会出现异常,要使用t2来管理线程。这也就意味着thread可以作为函数的返回类型,或者作为参数传递给函数,能够更为方便的管理线程。

线程的标识类型为std::thread::id,有两种方式获得到线程的id。

  • 通过thread的实例调用get_id()直接获取
  • 在当前线程上调用this_thread::get_id()获取

对于两个线程有可能出现数据等竞争的情况,这时,要利用操作系统线程方面的知识进行调度,这里仅举一个简单例子,使用互斥锁。在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。比如说,同一个文件,可能一个线程会对其进行写操作,而另一个线程需要对这个文件进行读操作,可想而知,如果写线程还没有写结束,而此时读线程开始了,或者读线程还没有读结束而写线程开始了,那么最终的结果显然会是混乱的。为了保护共享资源,在线程里也有这么一把锁——互斥锁(mutex),互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁( lock )和解锁( unlock )。互斥锁封装在mutex类中,通过调用类成员函数lock()和unlock()来实现加锁和解锁。值得注意的是,加锁和解锁,必须成对使用,这也是比较好理解的。除此之外,互斥量的使用时机,就以开篇程序为例,我们要保护的共享资源当然就是消息队列list了,那么互斥锁应该加在哪里呢

#include <iostream>
#include <thread>
#include <Windows.h>
#include <mutex>
  
using namespace std;
  
mutex mu;  //线程互斥对象
  
int totalNum = 100;
  
void thread01()
{
    while (totalNum > 0)
    {
        mu.lock(); //同步数据锁
        cout << totalNum << endl;
        totalNum--;
        Sleep(100);
        mu.unlock();  //解除锁定
    }
}
void thread02()
{
    while (totalNum > 0)
    {
        mu.lock();
        cout << totalNum << endl;
        totalNum--;
        Sleep(100);
        mu.unlock();
    }
}
  
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.detach();
    task02.detach();
    system("pause");
}