linux线程使用

概念:

(1)PCB(Process Control Block)进程管理块:系统中存放进程的管理和控制信息的数据结构体,每一个进程均有一个PCB,在创建进程时建立,直到进程撤销而撤销。

(2)程序段:是进程中能被进程调度程序在CPU上执行的程序代码段。

(3)数据段:一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行后产生的中间或最终数据。

从结构上看,进程由程序段、数据段和PCB三部分组成。

(4)进程:进程是正在运行的程序的实例,是系统进行资源分配和调度的基本单位。

(5)线程:线程是操作系统能够进行运算调度的最小单位,被包含在进程里面,是进程中的实际运作单位,可以与同属一个进程的其他线程共享进程所拥有的全部资源。

线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,并且至少有一个线程。

进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位。

linux系统原本没有线程,后来受windows多线程编程影响,做出了类似windows线程的Linux版本的线程,但是归根结底还是进程,只不过是轻量及的进程,开销会比真正的进程要小的多。

实现:增加线程后,线程均分进程原有的PCB,原先的进程退化为主线程。但是PCB占用总和并没有变,所以并没有提升效率,对于内核而言,线程依旧是进程,但是线程间通信共享资源等会方便的多。

---------------------------------------------------------------------------------------------------

Linux下编写C程序,头文件中包含pthread.h,但是报错:对 'pthread_create'未定义的引用。

原因:phthread库不是linux系统的默认库,连接时需要使用libpthread.a库,编译时需要写:gcc test.c -lpthread

--------------------------------------------------------------------------------------------------

创建线程:int pthread_create(pthread_t *pthread, const pthread_attr_t *attr, void *(start_routine)(void*), void *arg)

                  pthread:返回线程ID。返回的是新创建的线程的ID

                  attr:设置线程的属性。一般为NULL,设置的是新线程的属性。

                  start_routine:函数地址。线程启动后执行的函数,是一个函数指针,指向线程的入口函数

                   arg:传给线程启动函数的参数。

                   函数返回值:成功返回0,失败返回错误码。

线程创建后,并不能保证哪个线程先执行,新创建的线程和调用线程的执行顺序不确定,由操作系统进行调度。

pthread_self():得到当前线程的ID。

终止线程:

(1)pthread_exit和pthread_join

         void pthread_exit(void *retval),retval是一个空指针,用来保存线程退出之后的返回值,成功返回0,失败返回错误码。这个指针必须是全局的或者被malloc分配的,当线程得到这个返回指针时程序已经退出

         int pthread_join(pthread_t thread, void **retval) :thread是线程指针,retval是用户定义的指针,用来存储被等待线程的返回值。

         使用:在线程中调用pthread_exit()函数,在主线程中在调用pthread_create()函数启动线程后,调用pthread_join()函数,等待线程结束。

linux线程使用_第1张图片

(2)取消一个执行中的线程:int pthread_cancel(pthread_t thread),成功返回0,失败返回错误码,thread是线程ID

和phread_join结合使用:(作用与进程中的kill()函数对应)

linux线程使用_第2张图片

       

 

(3)只终止某个线程,而不终止整个进程:从需要终止的函数return。此方式对主线程不适用,从main函数return相当于exit。

linux线程使用_第3张图片

获取当前线程ID的函数:phtread_t pthread_self(void)

获取当前文件中国线程tid的命令:ps -eLf | head -1&& ps -eLf | grep a.out

-------------------------------------------------------------------------------------

互斥锁:保证共享数据的完整性。

pthread_mutex_t:互斥变量,一个锁类型的结构体。保证任一时刻,只有一个线程来访问对象。

(1)创建互斥锁:pthread_mutex_t mtx;

(2)互斥锁初始化:

        <1> 动态方式:int pthread_mutex_init( pthread_mutex_t *mutex, const pthread_mutexattr_t *mattr)

               mutex:互斥锁;mattr:互斥锁属性,为空使用缺省值。函数成功返回0,执行成功后,互斥锁被初始化锁住状。

        <2> 静态方式:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

(3)加锁

        <1> 阻塞方式:int pthread_mutex_lock(pthread_mutex_t *mutex)

                如果参数mutex所指的互斥体已经被锁住了,那么发出调用的线程将被阻塞直到其他线程对mutex解锁

        <2> 非阻塞方式:int pthread_mutex_trylock(pthread *mutex)

                如果参数mutex所指的互斥锁已经被锁住,发出调用的线程不会阻塞等待,而会返回一个错误码

(4)解锁

         int pthread_mutex_unlock(pthread_mutex_t *mutex)

(5)销毁锁

        int pthread_mutex_destroy(pthread_mutex_t *mutex)

-------------------------------------------------------------------------------------

练习:

<1>

linux线程使用_第4张图片

问题1:为什么主函数中不调用pthread_join()函数,调用的线程就没有输出?

原因:pthread_join()函数以阻塞的方式使一个线程来等待另一个线程的结束。代码中若没有pthread_join()函数,主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会执行就结束了。主线程调用pthread_join()之后,就会等待函数等待的线程结束后再退出。

mian函数是一个进程,当main函数里创建线程之后,main函数从进程退步为主线程。

<2>互斥锁的使用

linux线程使用_第5张图片

在线程调用的程序段前后加解锁之后,线程会排队调用程序段。

 

 

 

 


 

 

 

       

 

        

 

        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(linux,c语言)