码迷,mamicode.com
首页 > 编程语言 > 详细

多线程编程基础

时间:2021-03-03 12:04:38      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:attribute   out   编程   arm   input   suspend   ret   输入   时间   

线程:进程上下文中执行的代码序列,又名轻量级进程。

在支持多线程的系统中,进程成为资源分配和保护的实体,线程是被调度执行的基本单元。进程是拥有资源的最小单位。

 

线程的分类

1)核心态线程(内核级线程):所有管理操作都是有操作系统内核完成的

2)用户态线程(用户级线程):一般我们操作的线程都是用户态线程。由用户级实现的线程 库来支持

 

用户级线程特征

1)用户级线程的创建和管理等操作无需内核参与,操作更快

2)并行性不高,一个线程被系统阻塞后,整个进程被阻塞

 

内核级线程特征

1)并行性高:多个线程可被提供是调度,充分利用多核处理器

2)创建和管理代价高

 

多线程(同一时刻可运行多个线程)优点

1)创建一个线程比创建一个进程的代价小

2)线程的切换比进程间的切换代价小

3)充分利用多核处理器

4)数据共享:使得线程之间的通信比进程间的通信更高效

5)快速响应特性:在系统繁忙的情况下,进程通过独立的线程及时响应用户的输入

 

Windows显示主要使用Win32 API实现

windows常用线程操作函数:创建线程函数、管理线程函数、终止线程函数、线程同步函数

 

线程必须从指定的函数开始,也就是这个函数其实就是线程的入口函数

DWORD WINAPI ThreadFunc(LPVOID IpvThreadParm);

 

线程创建函数是Windows API标准函数

技术图片
HANDLE CreateThread(

LPSECURITY_ATTRIBUTES  IpThreadAttributes //安全属性,设为null就可以

SIZE_T                 dwStackSize,     //内存的大小,栈的大小  可以为0

LPTHREAD_START_ROUTINE IpStartAddress,  //函数的指针,指向线程函数

LPVOID                 IpParameter,     //传递的参数,可以为空

DWORD                  dwCreationFlags,  //创建标志,只能为0或者CREATE_SUSPENDED.0表示创建之后就会执行,CREATE_SUSPENDED表示创建之后处于挂起状态(观其计数器为1)

LPDWORD                IpThreadId        //线程的ID好,可以不写

);//返回值是句柄
View Code

 

_beginthread函数是vc里面创建线程的函数。里面的实质还是API的创建函数

技术图片
hThread=_beginthread(

void(*strat_address)(void *),//线程函数的指针

unsigned stack_size,  //栈的大小

void *arglist //参数列表

);
View Code

 

 示例

技术图片
#include<stdio.h>
#include<windows.h>
#include<process.h>
#include<iostream>
#include<fstream>
using namespace std;

void ThreadFunc1(PVOID param){
    while(1){
        Sleep(1000);
        cout<<"This is ThreadFunc1"<<endl;
    }
}

void ThreadFunc2(PVOID param){
    while(1){
        Sleep(1000);
        cout<<"This is ThreadFunc2"<<endl;
    }
}

int main(){
    int i=0;
    _beginthread(ThreadFunc1,0,NULL);
    _beginthread(ThreadFunc2,0,NULL);
    
    Sleep(3000);
    cout<<"end"<<endl;
    cin>>i;//这句话是为了让主程序停止在这里
    
    return 0; 
}
View Code

 

 

线程是一个函数的表示方法

在时间片轮转中,主线程有优先权(主线程结束,子线程自动结束),跟编译器有关

main是主线程,另外两个是子线程,主线程走自己的,子线程也走自己的,三个线程同时执行

主线程死掉,子线程自动结束,三个线程是独立的。

这三个线程加上其余计算机上的线程一起在windows中进行调度,所以即便是先创建线程1,再创建线程2,但是也有可能先执行线程2再执行线程1.所以多次运行结果会不同

在分配给CPU区域的时候,该CPU可能将其挂起等等操作。队列也不同。最后结果可能就千差万别。需要使用更多的函数,使得线程满足我们自己的需求

 

进程中的每个线程都有挂起计数器。当挂起计数器为0时,线程被执行;当挂起计数器大于0时,调度器不去调取该线程

 

挂起线程函数  挂起计数器加1

技术图片
DWORD SuspendThread(

HANDLE hThread;//线程函数的句柄

);
View Code

 

解挂函数   挂起计数器减1

技术图片
DWORD ResumeThread(

HANDLE hThread  //线程函数的句柄

);
View Code

 

线程终结函数

线程内部终结线程

VOID ExitThread(DWORD dwExitCode);//参数:退出码(线程以什么方式退出)

 

在线程外终结线程

技术图片
BOOL TerminateThread(//返回值bool表示执行成功还是失败

HANDLE hThread,  //被终止的线程的函数名(句柄)

DWORD dwExitCode //退出码

);
View Code

 

示例

技术图片
#include<stdio.h>
#include<windows.h>
#include<iostream>
using namespace std;

DWORD WINAPI FunOne(LPVOID param){
    while(true){
        Sleep(1000);
        cout<<"hello!";
    }
    return 0;
}

DWORD WINAPI FunTwo(LPVOID param){
    while(true){
        Sleep(1000);
        cout<<"world!";
    }
    return 0;
}

int main(){
    int input=0;
    HANDLE hand1=CreateThread(NULL,0,FunOne,(void *)&input,CREATE_SUSPENDED,NULL); 
    HANDLE hand2=CreateThread(NULL,0,FunTwo,(void *)&input,CREATE_SUSPENDED,NULL); 
    
    while(true){
        cin>>input;
        if(input==1){
            ResumeThread(hand1);
            ResumeThread(hand2);
        }
        else {
            SuspendThread(hand1);
            SuspendThread(hand2); 
        }
    }
    
    TerminateThread(hand1,1);
    TerminateThread(hand2,1);
    return 0;
}
View Code

 

多线程编程基础

标签:attribute   out   编程   arm   input   suspend   ret   输入   时间   

原文地址:https://www.cnblogs.com/sunjianzhao/p/14470016.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!