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.join
或t1.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");
}