精华内容
下载资源
问答
  • linux多线程编程指南

    2017-07-30 17:39:53
    linux多线程编程指南
  • 线程  线程是计算机中独立运行的... 使用多线程的理由之一是和进程相比,它是一种非常“节俭”的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它
  • linux多线程编程

    2020-12-13 13:54:59
    线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。...现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux
  • Linux多线程编程手册

    2018-06-02 15:19:14
    本手册详细介绍Linux多线程编程同步技术,可供广大linux工程师参考
  • Linux多线程编程

    千次阅读 2019-06-21 17:40:29
    作为多任务实现的一种机制,多线程应用得非常广泛,相对于多进程,多线程不仅运行效率高,...一、多线程编程常用函数 1. int pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * (*start_ro...

    作为多任务实现的一种机制,多线程应用得非常广泛,相对于多进程,多线程不仅运行效率高,而且还可以提高系统资源的使用效率。虽然网上关于多线程的讲解已经有一大堆,但出于学习的心态,有必要在这里做一下笔记。

    一、多线程编程常用函数

    1. int pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * (*start_routine)(void *), void *arg);

    作用:创建一个新线程

    参数:

     thread:线程ID

     attr:线程属性(包括调度策略,调度参数,堆栈地址,堆栈大小等)。一般设置为NULL,即采用系统默认属性

     void * (*start_routine):线程函数指针

     *arg:线程函数参数的指针

     返回值:

    0:表示创建成功

    其他:表示创建失败失败

     2. int pthread_join(pthread_t th, void **thread_return);

    作用:等待其他线程终止

    参数:

    th:需要等待的线程的ID

    thread_return:所等待的线程的返回值

    返回值:

    0:表示成功

    其他:表示失败

    3. void pthread_exit(void *retval);

    作用:终止当前线程

    参数:

    retval:线程的返回值

    4. int pthread_mutex_lock(pthread_mutex_t *mutex);

    作用:上锁,如果锁不可用则会阻塞当前线程直到锁可用

    参数:

    mutex:互斥变量

    5. int pthread_mutex_unlock(pthread_mutex_t *mutex);
    作用:与pthread_mutex_lock()相反

    6. pthread_t pthread_self(void);

    作用:返回当前线程ID

    返回值:

    当前线程ID

    7. int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

    作用:解锁mutex,等待条件变量cond被发出信号

    参数:

    cond:条件变量

    mutex:互斥锁对象

          在调用此函数之前要先获得互斥锁,调用此函数时会自动释放互斥锁以防止死锁,这就是为什么此函数与互斥锁联系在一起的原因。另外此函数调用成功后当前线程会被挂起并放弃CPU,因此在等待的过程中是不会占用CPU资源的,当条件满足(被唤醒)时会重新上锁。

    8. int pthread_cond_signal(pthread_cond_t *cond);

    作用:重新开始(唤醒)正在等待条件变量cond的线程

    参数:

    cond:条件变量

    二、实例

           要求:在主线程里创建两个子线程,其中一个子线程输出1,3,5,7,9,另一个子线程输出2,4,6,8,10,输出的顺序是1,2,3,4,5,6,7,8,9,10。两个子线程都退出后主线程才退出。

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


    //初始化互斥锁
    pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
    //初始化条件变量
    pthread_cond_t  condition_var   = PTHREAD_COND_INITIALIZER;
    //初始化计数变量
    int num = 1;

    //线程1的线程函数
    void *thread1(void *arg)
    {
        while(1)
        {
            //上锁
            pthread_mutex_lock( &count_mutex );    
            //如果num是奇数
            if(num%2)
            {    
                //输出当前num的值
                printf("thread1 create: %d\n",num);
                num++;    
            }
            else
                //解锁,等待
                pthread_cond_wait( &condition_var, &count_mutex );
            //解锁
            pthread_mutex_unlock( &count_mutex );
            if(num > 10)
                return NULL;
        }
        
    }

    //线程2的线程函数
    void *thread2(void *arg)
    {
        while(1)
        {
            //上锁
            pthread_mutex_lock( &count_mutex );    
            //如果num是偶数
            if(!(num%2))
            {    
                //输出当前num的值
                printf("thread2 create: %d\n",num);
                num++;    
            }
            else
                //唤醒正在等待的线程
                pthread_cond_signal( &condition_var );
            
            //解锁
            pthread_mutex_unlock( &count_mutex );
            if(num > 10)
            {
                //最后再唤醒一次以防止死锁
                pthread_cond_signal( &condition_var );
                return NULL;
            }
        }

    }


    int main()
    {
        pthread_t t1,t2;
        int ret;
     
        //创建线程1
        ret = pthread_create(&t1,NULL,thread1,NULL);
        if(ret != 0)    
        {
            printf("pthread_create 1 failed!\n");
        }
        
        //创建线程2
        ret = pthread_create(&t2,NULL,thread2,NULL);
        if(ret != 0)    
        {
            printf("pthread_create 2 failed!\n");
        }

        //等待线程1结束
        ret = pthread_join(t1,NULL);
        if(ret != 0)
        {
            printf("pthread_join 1 failed!\n");        
        }    

        //等待线程2结束
        ret = pthread_join(t2,NULL);
        if(ret != 0)
        {
            printf("pthread_join 2 failed!\n");
        }

        return 0;
    }

    编译后运行,结果如下:

     

    展开全文
  • 我只想要进程的某个线程休眠一段时间的,可是用sleep()是将整个进程都休眠的,这个可能达不到,我们想要的效果了。目前我知道有三种方式:  1、usleep  这个是轻量级的,听说能可一实现线程休眠,我个人并不...
  • 本文主要对Linux下的多线程进行一个入门的介绍,虽然是入门,但是十分详细,希望大家通过本文所述,对Linux多线程编程的概念有一定的了解。具体如下。 1 线程基本知识 进程是资源管理的基本单元,而线程是系统调度的...
  • 通过几个实验练习,学习线程之间连接的具体实现。下面列举了两个例子,一个是子线程返回简单数据类型;另一个是子线程返回复杂数据类型。 实现代码 子线程返回复杂数据类型 #include #include #include #include ...
  • 操作系统上机-Linux多线程编程
  • Linux 多线程编程笔记——简单、好记、好用说明:本代码参考麦子学院魏杰老师的Linux多线程编程 视频教程,整理有参考网上的做出修改,自己也可以参考网上比较好的例程
  • LINUX 多线程编程资料,主要讲解LINUX网络编程多线程这一块。
  • Linux多线程编程入门

    2021-01-20 14:55:49
     需要注意的是:即使程序运行在单核处理器上,也能够得到多线程编程模型的好处。处理器的数量并不影响程序结构,所以不管处理器个数多少,程序都可以通过线程得以简化。  linux操作系统使用符合POSI
  • 第四讲 Linux多线程编程;进程与线程一;进程与线程二;多线程程序的优点;多线程编程起步;int main(void) { pthread_t id; int i,ret; ret=pthread_create&id,NULL(void ) thread,NULL; if(ret!=0){ printf "Create ...
  • LINUX多线程编程

    2018-03-17 17:26:19
    这是关于在linux上进行多线程编程的教学文档,可以从中学到基础的TCP/IP协议、UDP协议下的多线程编程
  • Linux多线程编程手册,linux多线程编程手册pdf,C,C++源码.zip
  • 还有多线程编程的一些细节问题,如线程之间怎样同步、互斥,这些东西将在本文中介绍。我在某QQ群里见到这样一道面试题: 是否熟悉POSIX多线程编程技术?如熟悉,编写程序完成如下功能: 1)有一int型全局变量g_Flag...
  • 多线程编程相关内容,涉及到多线程的概念属性和特点以及如何运用,有相对应的例子可供参考,算是比较全面系统,整理来源网络和各博主的分享,上传方便查阅和学习
  • Linux多线程编程小结

    2021-01-20 14:52:09
     Linux进程创建一个新线程时,线程将拥有自己的栈(由于线程有自己的局部变量),但与它的创建者共享全局变量、文件描写叙述符、信号句柄和当前文件夹状态。  Linux通过fork创建子进程与创建线程之间是有差别的...
  • 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待条件变量的条件成立而挂起(此时不再占用cpu);另一个线程使条件成立(给出条件成立信号)。为了防止竞争,条件变量的使用...
  • 嵌入式Linux多线程编程C语言源码
  • linux多线程设计是指基于Linux操作系统下的多线程设计,包括多任务程序的设计,并发程序设计,网络程序设计,数据共享等。Linux系统下的多线程遵循POSIX线程接口,称为pthread。
  • Linux 多线程编程 (典藏、含代码)

    千次阅读 多人点赞 2020-02-11 17:31:40
    目录 1.基础知识 2. 相关函数 2.1创建线程 ----------- pthread_create ...2.3等待线程结束 ----------- pthread_join / 线程的分离 ----------- pthread_detach 2.4线程退出 2.4.1 正常退出pthr...

     

    目录

    1.基础知识

    2. 相关函数

    2.1创建线程 ----------- pthread_create

    2.2获取线程ID ------------ pthread_self

    2.3等待线程结束 ----------- pthread_join  /  线程的分离 ----------- pthread_detach

    2.4线程退出

          2.4.1 正常退出 pthread_exit

          2.4.2 非正常退出 pthread_cancel

    2.5线程退出处理函数 ----------------- pthread_cleanup_push/pthread_cleanup_pop

    2.6线程的属性

    2.6.1初始化属性结构和销毁属性结构 ----------- pthread_attr_init / pthread_attr_destroy

    2.6.2属性设置和获取函数 pthread_attr_setdetachstate / pthread_attr_getdetachstate

    2.7多进程和多线程的接口比较

    3. 线程的互斥和同步

    3.1概念

    3.2互斥锁

    3.3信号量

    3.3.1无名信号量的编程方法:

    3.3.2有名信号量的编程方法:

    3.4条件变量


     

    1.基础知识

        进程我前面已经讲解过了(链接),其实进程就是一个的程序文件加载到了内存,然后在内存中创建--运行--消亡的过程

        而线程是进程里面的,在C/C++中main函数可以理解为是一个进程的线程(主线程)

        多线程就是一个进程可以由多个线程完成代码的并行处理

     

        多线程属于轻量级的代码并行,之所以是轻量级,  是因为线程不需要额外创建过多的内存空间(因为线程可以共享进程的进程空间,无需像多进程那样重新又复制一遍进程空间),而它只需要一个线程栈,可以理解为一个线程其实就是一个函数,这每个函数可以同时处理,所以一般并行处理优先考虑多线程,而不是多进程

     

        多线程之间既相互独立(拥有自己的线程栈),又相互影响(共享进程空间). 而因为这种影响导致了对于同一资源不同的线程分别同时进行读和写造成的数据混乱问题, 因此在多线程之中大量用到互斥和同步技术(下面有详细的讲解)

     

        每个进程都有一个主线程,就是main函数,当主线程结束,进程也会结束, 进程空间释放了,其它线程也一起结束   

        线程的线程函数是可以一样(代码一样), 即可以是共用一个函数代码, 但是其实在运行的时候它们的线程栈是独立的

        Linux中,创建多个线程或者进程后,它们的执行顺序是不确定的 (可以用同步机制, 使得顺序确定 )

        没有“父子线程”的说法

     

    如何编译:

        Linux本身没有实现线程,在Linux中使用线程需要借助第三方线程库,在Linux使用多线程常使用pthread库

        使用pthread库时包含头文件 pthread.h,编译时要链接pthread库(-pthread),pthread库中的所有函数都以pthread_开头

        例如

    gcc main.c -o main -pthread

     

    2. 相关函数

    2.1创建线程 ----------- pthread_create

                  创建的线程和原线程一起运行,谁先谁后不确定

             

             参数:

                      thread - 传出参数,传出创建线程的ID

                      attr - 线程属性(给NULL表示使用默认属性)

                      start_rountine - 线程函数(线程执行的代码)

                      arg - 线程函数的参数

              成功返回0,失败返回错误码

     

    2.2获取线程ID ------------ pthread_self

             

     

    2.3等待线程结束 ----------- pthread_join  /  线程的分离 ----------- pthread_detach

            

            参数:

                    thread - 要等待的线程ID

                    retval - (类型为void **), 是传出参数,传出结束线程的返回值

            成功返回0,失败返回-1

     

            注⚠️:线程结束后应该由主线程回收资源,如果不回收,会变成僵尸线程,消耗系统资源,线程的资源回收既可以使用pthread_join让主线程等待线程结束然后再回收,也可以将线程设置为分离状态(detach)这样主线程就不用去堵塞等待

           分离状态的线程结束(退出)后自动回收资源,不需要主线程通过pthread_join等待回收

           将线程设置为分离状态 ----------- pthread_detach (也可以通过2.6.2方法进行属性配置)

           

          传入要设置的线程ID

     

    2.4线程退出

          2.4.1 正常退出 pthread_exit

               线程的正常退出有以下两种方式:

               1、在线程函数中执行return语句(不会执行退出处理函数)

               2、调用了pthread_exit函数退出(可以执行退出处理函数, 这个函数可以由程序猿自己定义,在2.5中有讲解)

                     

                     参数就是线程函数的返回值

     

          2.4.2 非正常退出 pthread_cancel

               线程的非正常退出有以下两种方式:

               1、线程执行时遇到错误(不会执行退出处理函数)

               2、被其他线程终止/取消(pthread_cancel)(可以执行退出处理函数, 这个函数可以由程序猿自己定义,在2.5中有讲解)

                     

                    参数就是要取消线程的ID,此外, 线程可以设置是否允许被取消(在2.6.2线程属性中讲解)

     

    2.5线程退出处理函数 ----------------- pthread_cleanup_push/pthread_cleanup_pop

        其中push函数用于往线程退出处理函数栈中 加入 退出处理函数,pop函数用于往线程退出处理函数栈中 取出 退出处理函数

        push 和 pop 必须成对出现,否则编译报错

        栈是先进后出

        

        push:

            routine - 退出处理函数

            arg - 传递给退出处理函数的参数

        pop:

            execute - 非0:取出执行

                            0:取出不执行

     

        退出处理函数在以下三种情况下会自动执行 :

        1、线程被其他线程取消(pthread_cancel),调用所有加入了的退出处理函数

        2、线程调用pthread_exit自己退出,调用所有加入了的退出处理函数

        3、执行pthread_cleanup_pop、同时传入非0参数时, 在线程退出处理函数栈中遵循先进后出原则取出一条退出处理函数,并执行它

     

    2.6线程的属性

        线程的属性在创建线程可以给定,线程运行期间某些属性可以修改

    2.6.1初始化属性结构和销毁属性结构 ----------- pthread_attr_init / pthread_attr_destroy

         

        使用属性前先调用init函数初始化,不再使用调用destroy函数销毁

    2.6.2属性设置和获取函数 pthread_attr_setdetachstate / pthread_attr_getdetachstate

        设置线程的分离/join属性:

        

        参数:

            attr - 属性

            deatchstate - 状态

                PTHREAD_CREATE_DETACHED - 分离状态

                PTHREAD_CREATE_JOINABLE - join状态(默认)

     

        设置线程是否允许被其他线程取消:

        

        state(状态):

            PTHREAD_CANCEL_ENABLE - 允许取消(默认)

            PTHREAD_CANCEL_DISABLE - 禁止取消

     

    2.7多进程和多线程的接口比较

    多线程和多进程编程有很多类似的地方, 这里我们将它们的相关函数作个对比:

     

     

    3. 线程的互斥和同步

    3.1概念

        我们知道,线程是共享同一个进程的进程空间,因此对于同一资源,不同线程同时去访问,会造成数据的混乱

        为了避免这种情况, 所以我们要用线程的互斥和同步

        互斥和同步的概念和进程中的互斥和同步是一个意思, 线程用的互斥和同步比进程用的更多, 由于线程共享的内容太多

        多线程之间共享所处进程的资源,因此很容易出现共享数据冲突。解决方案就是将线程对共享资源的访问由并行改为串行,实现这种串行访问的技术就是我们所谓线程的互斥和同步技术

        多线程中实现互斥和同步的技术包括:互斥锁 信号量 条件变量

        其中互斥锁和信号量常用于互斥,条件变量用于同步

     

    3.2互斥锁

        互斥锁也叫互斥量,常用于互斥

        属于pthread线程库里面的

        加锁只能加1次

    1)声明初始化互斥锁

        pthread_mutex_t lock;

        pthread_mutex_init(&lock,NULL);

    or

        pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

    2)加锁/上锁 --------- 访问共享资源前

        pthread_mutex_lock(&lock); ---------- 阻塞加锁(等待直到加锁成功)

        pthread_mutex_trylock(&lock);------- 非阻塞加锁(不管是否加锁成功都立即返回,成功返回0,失败返回非0)

    3)执行访问共享资源的代码

    4)解锁 ------------- 访问完共享资源

         pthread_mutex_unlock(&lock);

    5)不再使用释放锁

        pthread_mutex_destroy(&lock);

     

    3.3信号量

         信号量常用于互斥

         信号量是一个计数器,用来控制访问共享资源的最大并行 线程/进程 数,工作原理和进程中的信号量集中的信号量是一样的, 但是它们是不一样的两个东西

        信号量不属于线程库的范围,只是一个辅助工具,使用信号量需要加头文件 semaphore.h

        信号量分为无名信号量和有名信号量,最常用是无名信号量

     

    3.3.1无名信号量的编程方法:

    1)声明初始化信号量

        sem_t sem;

        sem_init(&sem,0,信号量初始值);

            第一参数是信号量的地址

            第二参数表示使用场景,0表示用于线程间,非0表示用进程间(无效)

            第三个参数就是信号量的初始值

    2)P操作(-1)

        sem_wait(&sem);

    3)执行访问共享资源代码

    4)V操作(+1)

        sem_post(&sem);

    5)不再使用销毁信号量

        sem_destroy(&sem);

     

    3.3.2有名信号量的编程方法:

    1)创建/打开有名信号量 ------- sem_open    

         

        参数:

            name - 有效的路径

            oflag - 打开标志(同open的标志)

            mode - 创建时有效,代表权限

            value - 创建时有效,代表初始值

         成功返回信号量的地址,失败返回SEM_FAILED

    2)P操作(-1)

          sem_wait(&sem);

    3)执行访问共享资源代码

    4)V操作(+1)

          sem_post(&sem);

    5)关闭信号量

         

        传入信号量地址

    6)不再使用删除信号量

        

        传入的是有名信号量的路径

     

    3.4条件变量

    1)概念

        常用于线程的同步

        条件变量的数据类型为 pthread_cond_t

        在多线程程序运行中,某个线程需要等待某个条件成立后再继续运行,这种等待可以在其他线程中唤醒

        条件变量的使用需要互斥锁的支持,用于防止条件竞争,这里被竞争的是条件变量

    2)条件变量编程步骤

    (1)分配初始化

        pthread_cont_t cond;

        pthread_cond_init(&cond,NULL);

    (2)等待条件成立

        

        代码如何写,格式如下(其中互斥锁的作用是防止条件竞争):

        //先加锁

        pthread_cond_wait(&cond,&lock);

        //执行使用条件的代码

        //解锁

     

    (3)唤醒等待条件的线程

        pthread_cond_signal(&cond); ------------ 唤醒一个等待条件的线程

        pthread_cond_broadcast(&cond); --------- 唤醒所有等待的线程(惊群)

     

    (4)不再使用可以删除

        pthread_cond_destroy(&cond);

     

    展开全文
  • LINUX 多线程编程资料,主要讲解LINUX网络编程多线程这一块。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 168,105
精华内容 67,242
关键字:

linux多线程编程

linux 订阅