Linux环境编程之多线程

可以认为一个进程就是只有一个线程的模型,那么多线程就是一个进程中有多个线程。下图很明显的说明了一个进程和线程的区别。多线程的代码段,数据段,文件描述符都是共享的,但是他们却有相互独立的寄存器和堆。

   
 
下面介绍线程中常用的函数,pthread大概有60多个函数,包括线程的创建、终止等。Linux中实现了pthread线程库,Unix/Widows中也有pthread的实现。 Linux中使用pthead方法为:头文件加上#include <pthread.h> ,在编译的时候要手动链接线程库,例如gcc main.c lpthread 。注意:必须加lpthread,不像glibc库,gcc不会自动去链接pthread库。
 
线程创建函数:pthread_create()
  
pthread_create用来创建一个线程。成功返回0,失败返回非0thread指向内存单元将被设置为新创建的线程IDattr是要创建线程的属性(NULL为默认属性),start_routine为线程开始执行的函数,argstart_routine的参数。线程共享全局变量,在一个线程中改变对另外线程可见。一下程序说明一个创建线程的过程。  
     
 arg不能是局部变量,否则线程使用该变量时可能已经被修改或者不存在了。start_routine的参数和返回值都为void *,如果有多个参数,那只能打包成一个结构体了。返回值不能是局部变量!! 主线程退出,则整个进程结束。参见以下代码示例
  
线程终止函数: 如果进程中的任意线程调用exit_exit_Exit那么整个进程都会被终止。 线程从启动函数中返回,返回值是线程的退出码。线程可以被其他线程取消,线程调用pthread_exit退出。
 
线程属性:
        
属性名称
说明
detachstate
线程的分离状态属性
guardsize
线程栈末尾的警戒缓冲区大小
stackaddr
线程栈的最低地址
stacksize
线程栈的大小(字节)
   线程分离属性:
通过pthread_join来回收这个线程控制块。如果设置了分离属性,那么线程结束时自动释放创建时分配的资源。pthread_detach用来 设置分离属性,但须注意必须在新创建的线程结束之前!一般来说这个函数是有新建线程进入启动函数后立马调用的,
pthread_detach(pthread_self())
   1.
       #include <pthread.h>
       int pthread_detach(pthread_t thread);
 
    2.
 #include <pthread.h>
 int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_init(pthread_attr_t *attr);
pthread_attr_init用默认值初始化线程的属性。成功返回0,失败返回非0值。pthread_attr_destroy用来销毁init分配的内存。该函数理论上都会执行成功,除非你传入了一个非法的属性指针。
    
#include <pthread.h>
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
成功返回0,失败返回非0
  
线程同步:线程同步主要解决了多线程之间访问同一文件的问题,如果A线程在写一个文件,此时B线程读取文件内容,这时就存在
一个同步的问题。解决这一问题有多种方法,比如互斥锁,读写锁,信号量等方式。这里只介绍互斥锁和读写锁,信号量实际上属于进
程间通信的内容。 互斥量其实就是一种锁,在访问共享数据之前设置这个锁,访问完之后释放这个锁。互斥量一旦被加了锁,其他任
何线程再也不能在这个互斥量上加锁,需等到锁被释放。
 
    当一个线程被创建时,系统给它创建一个线程控制块(有thread id来标识)。如果线程没有设置分离属性,那么需要其它线程
pthread_create的第二个参数就是线程的属性,传入NULL表示使用默认属性。可以用过pthread API来修改线程的属性。
调用pthread_exit后,线程终止。参数value_ptr会被后来调用pthread_join函数的线程获得。pthread_join的第一个参数指定某个线程,第二个参数用来接收线程的退出值。见以下代码
调用函数创建pthread_mutex_init函数的第一个参数接受该函数创建的互斥量。第二个参数为互斥量属性,可以为NULL
pthread_mutex_destroy用来销毁有init函数创建的互斥量,如果是静态创建的则无需调用destroy函数。 两个函数都是成功返回0,失败
返回非0值。
互斥量加锁:
int pthread_mutex_lock(pthread_mutex_t *mutex);
给互斥量mutex加锁。如果此互斥量已经加锁,那么调用该函数的线程会被阻塞,如果互斥量没加锁,调用线程给该互斥量加锁。
参数mutex是有init函数创建或者静态初始化。成功返回0,失败返回非0.
 
int pthread_mutex_trylock(pthread_mutex_t *mutex);
只是尝试加锁,看锁是否能加上。
如果所能加上则返回0,不能加上errno设置成EBUSY,错误返回其余值。 参数mutexlock函数一样。成功返回0,失败返回非0 线程可以用trylock去检查某个mutex是否加锁。如果加锁了,它就先去执行其它任务,以此增加并发性!互斥量的类型为pthread_mutex_t,要创建一个互斥量要么使用静态方式创建(PTHREAD_MUTEX_INITIALIZER 来初始化),要么多线程具有以下优点:上下文切换快,共享数据容易,创建线程速度快;缺点则是:内存共享会导致互相干扰,一个线程崩溃会导致整个进程崩溃。
 
int pthread_mutex_unlock(pthread_mutex_t*mutex);
释放互斥量
下面是一个互斥量加锁和解锁的过程,这个代码实现了先加锁,在线程中加一个数,然后解锁的过程。
读写锁:
读写锁提供了一种更为优雅的方式解决线程间的同步问题,互斥锁太TM霸道了,如果多个线程都是读这个文件,就不存在这样 的问题,而读写锁提供的机制就是读文件时不加锁,写文件时才加锁,写完了锁才释放掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值