Linux-----线程

多线程开发在 Linux 平台上已经有成熟的 pthread 库支持。其涉及的多线程开发的最基本概念主要包含三点:线程,互斥锁,条件。其中,线程操作又分线程的创建,退出,等待 3 种。互斥锁则包括 4 种操作,分别是创建,销毁,加锁和解锁。条件操作有 5 种操作:创建,销毁,触发,广播和等待。其他的一些线程扩展概念,如信号灯等,都可以通过上面的三个基本元素的基本操作封装出来。

Linux多线程编程初探 - 峰子_仰望阳光 - 博客园

什么是进程?什么是线程?进程与线程的区别?

一个进程在运行时候要给他分配内存、维护他的数据段、代码段以及堆栈等等

而线程与进程公用这些东西,开辟多个线程,不会分配多个内存,相对于多进程线程是非常节俭的一个多任务的操作方式。

线程的优点?

①非常节俭,切换效率远远快于进程,一个进程的开销是一个线程的三十倍左右

②进程间的通信很不方便需要信号量、共享内存、消息队列等等,很消耗cpu、内存的一个通信方式而线程不一样,线程共享这些内存,数据改变我们直接读取就可以知道数据的改变,并不需要过多的一些操作。

我们有办法去控制共享变量带来的一些问题,用到条件变量和互斥锁来访问

一、创建线及退出示范:

运用

int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);创建线程函数

线程参数说明:

①第一个参数是一个指针,当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID

②第二个参数是线程属性,一般NULL。attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。

③第三个参数是启动这个线程后,要调用那些函数。

④第四个参数,(是传入第三个调用函数的参数)

 //int pthread_join(pthread_t thread, void **rval_ptr);线程等待函数(后面二级指针参数,可以传各种参数例如,指针、整型数、结构体等等)

(unsigned long)pthread_self() 是一种函数,功能是获得线程自身的ID。

#include<stdio.h>
#include<pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
//pthread_t pthread_self(void);
void *func1(void *arg){
        printf("t1: pthread is num:%ld\n",(unsigned long)pthread_self());
        printf("t1:pram is%d ",*((int *)arg));

}
int main(){

        int ret;
        int pram=100;
        pthread_t t1;

        ret = pthread_create(&t1,NULL,func1,(void *)&pram);
        if(ret == 0){
                printf("main:func1 create success\n");
        }
        printf("main: %ld\n",(unsigned long)pthread_self());
        //int pthread_join(pthread_t thread, void **rval_ptr);
        pthread_join(t1,NULL);

        return 0;
}

2. 线程退出

  单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:

  1)线程只是从启动例程中返回,返回值是线程的退出码。

  2)线程可以被同一进程中的其他线程取消。

  3)线程调用pthread_exit:

#include <pthread.h>
int pthread_exit(void *rval_ptr);

3. 线程等待( pthread_join() )

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号

  调用这个函数的线程将一直阻塞直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果例程只是从它的启动例程返回i,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。

  可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。

  如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。

#include <stdio.h>
#inciude <pthread.h>

void(void *arg){

    stdatic int ret = 1;
    printf(" t1 : child pthread number is :$ld",(unsigned long)pthread_self);
    printf(" t1 : pram is :%d",&((int *)arg));

    prhread_exit((void *)&ret);
}

int main(){
        
    ...
    ...//线程创建例程省略
    pthread_t t1;
    int *pstr;
        
    ...    
    pthread_join(t1,(void **)&pstr);//(第二个参数一般为NULL,也可以将线程返回值传递回来,也就是收集线程的退出状态)
   
    return 0;
}
//void pthread_exit(void *rval_ptr);

二、线程间共享内存空间

线程间运行存在竞争的关系,不绝对先后顺序(可控制,线程同步的问题)

例程:创建t1 t2线程,   main t1 t2三者接续不重复从0++开始输出

#include<stdio.h>
#include<pthread.h>
int date_a = 0;

void *func1(void *arg){
        printf("t1: pthread is num:%ld\n",(unsigned long)pthread_self());
        printf("t1:pram is%d ",*((int *)arg));   //t1子进程
         while(1){
                        printf("t1:%d\n",date_a++);
                        sleep(1);
                }
}

void *func2(void *arg){
        printf("t2: pthread is num:%ld\n",(unsigned long)pthread_self());
        printf("t2:pram is%d ",*((int *)arg));   //t2子进程
         while(1){
                        printf("t2:%d\n",date_a++);
                        sleep(1);
                }
}

int main(){

        int ret;
        int pram=100;
        pthread_t t1;
        pthread_t t2;

        ret = pthread_create(&t1,NULL,func1,(void *)&pram);
        ret = pthread_create(&t2,NULL,func2,(void *)&pram);

        //int pthread_join(pthread_t thread, void **rval_ptr);
        while(1){
               printf("main:%d\n",date_a++);
                sleep(1);//主函数进程
         }

        pthread_join(t1,NULL);
        return 0;
}

三、线程同步之互斥量加锁解锁

对于多线程程序来说,我们往往需要对这些多线程进行同步。同步(synchronization)是指在一定的时间内只允许某一个线程访问某个资源。而在此时间内,不允许其它的线程访问该资源。我们可以通过互斥锁(mutex),条件变量(condition variable)和读写锁(reader-writer lock)来同步资源。

1. 创建及销毁互斥锁

#include <pthread.h>
①int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
②int pthread_mutex_destroy(pthread_*mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号

一、首先,创建一个共享变量(创建锁:pthread_mutex_t mutex;

然后,函数①main函数里初始化锁int pthread_mutex_init(锁的地址&mutex,NULL(属性))

        在程序退出后销毁锁(main的最后)int pthread_mutex_destroy(&mutex);

二、在线程内部加锁--解锁

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号

枷锁pthread_mutex_lock(&mutex);

解锁pthread_mutex_unlock(&mutex);

三、互斥锁进入死锁,什么情况造成死锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值