多线程编程

1 为什么要使用多线程

在编写代码时,是否会遇到以下的场景会感觉到难以下手? 要做 2 件事,一件需要阻塞等待,另一件需要实时进行。例如播放器:一边 在屏幕上播放视频,一边在等待用户的按键操作。如果使用单线程的话,程序必 须一会查询有无按键,一会播放视频。查询按键太久,就会导致视频播放卡顿; 视频播放太久,就无法及时响应用户的操作。并且查询按键和播放视频的代码混 杂在一起,代码丑陋。 如果使用多线程,线程 1 单独处理按键,线程 2 单独处理播放,可以完美解 决上述问题。

2 线程概念

所谓线程,就是操作系统所能调度的最小单位。普通的进程,只有一个线程在执行对应的逻辑。我们可以通过多线程编程,使一个进程可以去执行多个不同的任务。相比多进程编程而言,线程享有共享资源,即在进程中出现的全局变量, 每个线程都可以去访问它

3 如何理解(多)线程与(多)进程

(1)一个线程只属于一个进程,一个进程可包含多个线程。

(2)多线程是一个应用程序划分为若干给可并行运行的线程,每条线程独立运行。多线程就是同时运行多个程序实例

(3)线程享有共享资源,进程中的全局变量,每个线程都可去访问它。

(4)简单来说,一个多进程相当于有多个main()函数,每个main()函数分别执行一个功能。多线程只有一个main()函数,但是里面有多个独立函数,每个函数用于执行一个功能,该函数就是一个进程。

多进程图解:

多线程图解

4 多线程编程中部分用法

4.1 创建线程

#include <pthread.h>                                #包含头文件

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routi ne) (void *), void *arg);                                            #创建新线程

(1)第一个参数为 pthread_t 指针,用来保存新建线程的线程号;

(2)第二个参数表示了线程的属性,一般传入 NULL 表示默认属性;

(3)第三个参数是一个函数指针,就是线程执行的函数。这个函数返回值为 void*, 形参为 void*。

(4)第四个参数则表示为向线程处理函数传入的参数,若不传入,可用 NULL 填充.

4.2互斥访问

static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;        #初始化互斥

                                                                                                量也可以调用宏来快速初始化

pthread_mutex_lock(&g_tMutex);                                #上锁                                

pthread_mutex_unlock(&g_tMutex)                                #解锁

4.3同步操作(条件变量)

条件变量(条件变量可代替信号量,条件变量使用时,与互斥量一起)

static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER;        #初始化同步量

static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;        #初始化互斥

                                                                                                量也可以调用宏来快速初始化

//线程A:等待条件满足

pthread_mutex_lock(&g_tMutex);

pthread_cond_wait(&g_tConVar, &g_tMutex);

/* 操作临界资源 */

pthread_mutex_unlock(&g_tMutex);

//线程B:唤醒等待g_ConVar的线程

pthread_cond_signal(&g_ConVar)

4.4信号量(同步操作)

int sem_init(sem_t *sem,int pshared,unsigned int value);    #使用信号量时,用该函数初始化

#include <pthread.h>                                        #包含头文件

int sem_wait(sem_t *sem);                                #作用为检测指定信号量是否有资源可

                                                                                用,若无资源可用会阻塞 等待

int sem_post(sem_t *sem);                                #会释放指定信号量的资源

注:当sem_post释放信号量后,sem_wait才能等到。

多线程编程实例

include <xxx.h>
...

static char g_but[100];
static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;    #初始化互斥量
static pthread_cond_t  g_ConVar = PTHREAD_COND_INITIALIZER;     #初始化同步量

static void *My_thread_func(void *data)
{
    while(1)
    {
        /*等待通知*/
        pthread_mutex_lock(&g_tMutex);    //获得互斥量
        pthread_cond_wait(&g_tConVar,&g_tMutex);    //判断体哦阿健是否成立,成立执行下面代码,
                                //不成立会去释放互斥量,继续等待,一旦当能返回,就表条件成功,
                                //并获得互斥量(等待唤醒)
        /*打印*/
        printf("recv:%s\n",g_buf);
        pthread_mutex_unlock(&g_tMutex);     //释放互斥量
    }
    return NULL;
}

int main(int argc,char ** argv)
{
    pthread_t tid;              //对于进程而言,每一个进程都有一个唯一对应的 PID 号来表示该
                             //进程,而对于线程而言,也有一个“类似于进程的 PID 号”,名为 tid
    int ret;
    char buf[1000];

    /*1.创建“接收线程”*/
    ret = pthread_create(&tid,NULL,My_thread_func,NULL);    
    if(ret)                       //判断是否创建成功
    {
        printf("pthread_create err!\n");
        return -1;
    }

    /*2.主线程读取标准输入,发信息接收线程*/
    while(1)
    {
        fgets(buf,1000,stdin);                   //---------|
        pthread_mutex_lock(&g_tMutex);   //上锁  //          |---->防止互斥量卡在主线程
        memcpy(g_buf,buf,1000)                   //---------|
        
        pthread_cond_signal(&g_ConVar);          //唤醒线程
        pthread_mutex_unlock(&g_tMutex);         //解锁
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值