Linux下多线程编程互斥锁和条件变量的简单使用(2)

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

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

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

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

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

在默认情况下,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,检错,如果该互斥量已经被上锁,那么后续的上锁将会失败而不会阻塞,否则与PTHREAD_MUTEX_TIMED_NP类型相同,这样就保证当不允许多次加锁时不会出现最简单情况下的死锁;(4)、PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

pthread_mutex_destroy函数:销毁(注销)线程互斥锁;销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。

pthread_mutex_lock:占有互斥锁(阻塞操作);互斥锁被锁定,如果这个互斥锁被一个线程锁定和拥有,那么另一个线程要调用这个函数就会进入阻塞状态(即等待状态),直到互斥锁被释放为止;互斥量一旦被上锁后,其它线程如果想给该互斥量上锁,那么就会阻塞在这个操作上,如果在此之前该互斥量已经被其它线程上锁,那么该操作将会一直阻塞在这个地方,直到获得该锁为止。

pthread_mutex_unlock:释放互斥锁;在操作完成后,必须调用该函数给互斥量解锁,这样其它等待该锁的线程才有机会获得该锁,否则其它线程将会永远阻塞。

与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。条件变量分为两部分:条件和变量。条件本身是由互斥量保护的。线程在改变条件状态前先要锁住互斥量。条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”(给出条件成立信号)。条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两线程共享可读写的内存,条件变量可以被用来实现这两线程间的线程同步。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ad14fc75ca0efbaffe73511019ccd1ab.html