设为首页 加入收藏

TOP

Linux下多线程编程互斥锁和条件变量的简单使用(一)
2015-11-10 13:45:43 来源: 作者: 【 】 浏览:24
Tags:Linux 线程 编程 条件 变量 简单 使用

Linux下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,链接时需要使用库libpthread.a。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但是它可与同属一个进程的其它的线程共享进程所拥有的全部资源。当多个任务可以并行执行时,可以为每个任务启动一个线程。


线程是并发运行的。在串行程序基础上引入线程和进程是为了提供程序的并发度,从而提高程序运行效率和响应时间。


与进程相比,线程的优势:(1)、线程共享相同的内存空间,不同的线程可以存取内存中的同一个变量;(2)、与标准fork()相比,线程带来的开销很小,节省了CPU时间,使得线程创建比新进程创建快上十到一百倍。


适应多线程的理由:(1)、和进程相比,它是一种非常“节俭”的多任务操作方式,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种“昂贵”的多任务工作方式。而运行一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间;(2)、线程间方便的通信机制。对不同的进程来说,它们具有独立的数据空间,要进行数据的传输只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。


多线程程序作为一种多任务、并发的工作方式,其优点包括:(1)、提供应用程序响应;(2)、使多CPU系统更加有效:操作系统会保证当线程数不大于CPU数目时,不同的线程运行在不同的CPU上;(3)、改善程序结构:一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序利于理解和修改。


pthread_create:用于在调用的进程中创建一个新的线程。它有四个参数,第一个参数为指向线程标识符指针;第二个参数用来设置线程属性;第三个参数是线程运行函数的起始地址;第四个参数是运行函数的参数。


在一个线程中调用pthread_create函数创建新的线程后,当前线程从pthread_create处继续往下执行。pthread_create函数的第三个参数为新创建线程的入口函数的起始地址,此函数接收一个参数,是通过第四个参数传递给它的,该参数的类型是void*,这个指针按什么类型解释由调用者自己定义,入口函数的返回值类型也是void*,这个指针的含义同样由调用者自己定义,入口函数返回时,这个线程就退出了,其它线程可以调用pthread_join函数得到入口函数的返回值。


pthread_join:线程阻塞函数,用于阻塞当前的线程,直到另外一个线程运行结束;使一个线程等待另一个线程结束;让主线程阻塞在这个地方等待子线程结束;代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了,加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。


pthread_create将一个线程拆分为两个,pthread_join()将两个线程合并为一个线程。


一个线程实际上就是一个函数,创建后,立即被执行,当函数返回时该线程也就结束了。


线程终止时,一个需要注意的问题是线程间的同步问题。一般情况下,进程中各个线程的运行是相互独立的,线程的终止并不会相互通知,也不会影响其它线程,终止的线程所占用的资源不会随着线程的终止而归还系统,而是仍然为线程所在的进程持有。一个线程仅允许一个线程使用pthread_join等待它的终止,并且被等待的线程应该处于可join状态,而非DETACHED状态。一个可”join”的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,因此为了避免内存泄露,所有线程终止时,要么设为DETACHED,要么使用pthread_join来回收资源。一个线程不能被多个线程等待。


所有线程都有一个线程号,也就是threadid,其类型为pthread_t,通过调用pthread_self函数可以获得自身的线程号。


Linux线程同步的几种基本方式:join、互斥锁(mutex)、读写锁(read-writelock)、条件变量(condition variables)。mutex的本质是锁,而条件变量的本质是等待。


互斥:简单的理解就是,一个线程进入工作区后,如果有其它线程想要进入工作区,它就会进入等待状态,要等待工作区内的线程结束后才可以进入。


互斥提供线程间资源的独占访问控制。它是一个简单的锁,只有持有它的线程才可以释放那个互斥。它确保了它们正在访问的共享资源的完整性,因为在同一时刻只允许一个线程访问它。


互斥操作,就是对某段代码或某个变量修改的时候只能有一个线程在执行这段代码,其它线程不能同时进入这段代码或同时修改该变量。这个代码或变量称为临界资源。


通过锁机制实现线程间的同步,同一时刻只允许一个线程执行一个关键部分的代码。


有两种方式创建互斥锁,静态方式和动态方式。


在默认情况下,Linux下的同一线程无法对同一互斥锁进行递归加锁,否则将发生死锁。所谓递归加锁,就是在同一线程中试图对互斥锁进行两次或两次以上的行为。解决问题的方法就是显示地在互斥变量初始化时将其设置成recursive属性。


互斥量是一种用于多线程中的同步访问的方法,它允许程序锁住某个对象或者某段代码,使得每次只能有一个线程访问它。为了控制对关键对象或者代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁。


互斥量用pthread_mutex_t数据类型来表示,在使用互斥变量之前,必须首先对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(如调用malloc)函数,那么释放内存前(free)需要使用pthread_mutex_destroy函数。


对共享资源的访问,要对互斥量进行加锁,如果互斥量已经上了锁,调用线程会阻塞,直到互斥量被解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。


pthread_mutex_init函数:主要用于多线程中互斥锁的初始化。如果要用默认的属性初始化互斥量,只需把第二个参数设置为NULL。互斥量的属性可以分为四种:(1)、PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁,当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁,这种锁策略保证了资源分配的公平性;(2)、PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许线程多次加锁,不同线程,解锁后重新竞争;(3)、PTHREAD_MUTEX_ERRORCHECK_NP,检错,如果该互斥量已经

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Caffe源码中各种依赖库的作用及简.. 下一篇libcurl库的使用(通过libcurl库下..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: