c++主线程和子线程

c++主线程和子线程

最近在学习c++多线程,写一篇博客记录下自己的收获。
一.main()函数是主线程函数,在main()函数中创建的线程属于子线程,那主线程和子线程的优先级谁更高呢?
可以看下另外一篇文档:link
在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。不过主线程先启动占用了cpu资源,如果存在主线程和子线程争抢cpu执行权的话,看运气,谁抢到就让谁执行。
其实设置了优先级,也无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。 线程的优先级用1-10之间的整数表示,数值越大优先级越高,默认的优先级为5。
下面来看一段简单的代码:

#include "stdafx.h"
#include <iostream>
#include "process.h"
#include "windows.h"
using namespace std;

void ThreadFun1(void *){
	cout << "这是子线程1" << endl;
}
void ThreadFun2(void *){
	cout << "这是子线程2" << endl;
}
int main(){     	
	_beginthread(ThreadFun1, 0, NULL); 
	_beginthread(ThreadFun2, 0, NULL);    
	cout << "end" << endl;
	return 0;  
}

这里定义了两个线程函数,并在主线程main()中创建了两个子线程。于是,此进程中有三个子线程,任一时刻cpu只运行一个进程,当cpu轮换到此进程时,到此会执行三个线程中哪一个呢?
多次运行结果如下:
在这里插入图片描述
可见,主线程总是能优先获得cpu的执行权,且主线程执行完成后,程序就退出了,子线程就再也没有执行的机会,即主线程结束,子线程也会被迫结束
为了让主线程获得cpu的执行权之后,程序不退出,可以在主线程中加入一个死循环,代码如下:

#include "stdafx.h"
#include <iostream>
#include "process.h"
#include "windows.h"
using namespace std;

void ThreadFun1(void *){
	cout << "这是子线程1" << endl;
}
void ThreadFun2(void *){
	cout << "这是子线程2" << endl;
}
int main(){     	
	_beginthread(ThreadFun1, 0, NULL); 
	_beginthread(ThreadFun2, 0, NULL);  
	cout << "end" << endl;
	while(1){}
	return 0;  
}

这样在第一回合的cpu争夺中,主线程获得执行权后程序也不会退出,在后续的cpu争夺回合中,子线程便有机会获得cpu的执行权。 程序的执行结果如下:
在这里插入图片描述在这里插入图片描述
第一次争夺中,主线程获得cpu执行权,然后执行循环,后续争夺中,某一回合子线程1或者2获得执行权(这里由于子线程内容较少,在一次时间片轮换中就把子线程执行完毕,即只要获得一次cpu执行权就可以执行完子线程),然后退出线程池,剩下的一个子线程和主线程继续争夺cpu的执行权,后面某一个回合中,剩下子线程也执行完毕,只剩下了主线程,便一直执行主线程中的循环。
而且也可以看出,两个子线程的执行顺序不定,即哪个子线程能先获得cpu的执行权得看运气。

二、如果想先执行子线程,然后执行主线程,应该采用什么方法?
这里介绍一个Sleep()函数,Sleep()函数的解释可以看这篇博客:link
大致内容如下:
当调用Sleep函数的时候,比如Sleep(400);它告诉系统,此线程将放弃此次运行的时间片,比方说现在线程只执行了10ms,按“有关部门规定”它被唤醒一次是要执行20ms的。这时它就说,这次机会我放弃,后面的10ms不要了。下次轮上我再叫我。 这样,系统便会将其终止,然后再一次进行调度选择。如果它运气很好,又被选中了,系统则会查看这个线程是否处于sleep标志中。如果发现他还需要继续睡眠,则重新进行调度选择,直到选择一个有权执行的线程为止。 如果很不幸,400ms到了,但是系统很忙,调度算法在很长一段时间也没有选择到这个线程,那这么线程就很继续休眠。于是说,这个Sleep(400);将导致这个线程会休眠大于等于400MS的时间。

关于这个函数更具权威的解释(抄书):
1、调用Sleep,可使线程自愿放弃它剩余的时间片。
2、系统将在大约的指定秒数内使线程不可高度。不错,如果告诉系统,想睡眠100MS,那么可以睡大约这么长的时间,但也也可能睡眠数秒或数分钟。记住,WINDOWS不是个实时操作系统。虽然线程可能在规定的时间被唤醒,但是它能否做到,取决于系统中还有什么操作正在进行。
3、可以调用Sleep(INFINITE),告诉系统永远不要调用这个线程。但最好不要这样,让线程退出就行了。反正你都不再需要它。或者调用Sleep(0);告诉系统线程将放弃剩于的时间片,并使系统调度另一个线程。但是,系统可以对刚刚调用Sleep的线程重新调度。如果不存在多个拥有相同优先级的可调度线程。就会出现这种情况。

加入Sleep()函数后的代码如下:

#include "stdafx.h"
#include <iostream>
#include "process.h"
#include "windows.h"
using namespace std;

void ThreadFun1(void *){
	while (1) {
		cout << "这是子线程1" << endl;
		Sleep(30);
	}
}
int main(){     	
	_beginthread(ThreadFun1, 0, NULL); 
	Sleep(300);
	cout << "end" << endl;
}

在这里插入图片描述
可以这么理解:主线程Sleep 300毫秒,在这300毫秒内,程序只能执行子线程,然而子线程执行完打印后,也进入Sleep(30),可以认为时是每30毫秒执行一次子线程。
如果把Sleep(30)放在cout之前;子线程执行9次,这个细微的差别请读者自行理解 。
最后可以让三个线程依次执行:

#include "stdafx.h"
#include <iostream>
#include "process.h"
#include "windows.h"
using namespace std;

void ThreadFun1(void *){
	cout << "这是子线程1" << endl;
}
void ThreadFun2(void *) {
	Sleep(30);
	cout << "这是子线程2" << endl;
}

int main(){     	
	_beginthread(ThreadFun1, 0, NULL); 
	_beginthread(ThreadFun2, 0, NULL);
	Sleep(300);
	cout << "end" << endl;
}

运行结果如下:
在这里插入图片描述
写在最后:
Sleep()函数并不能严格保证线程按顺序执行,如上面的程序,如果子线程1内容很多,代码无法在30毫秒内完成,因此当子线程2休眠完毕后,两个子线程依然会继续争夺cpu。故无法保证线程能按顺序执行。

相关推荐
©️2020 CSDN 皮肤主题: 鲸 设计师:meimeiellie 返回首页