【Linux】互斥锁

来源:互联网 发布:java互联网开发框架 编辑:程序博客网 时间:2024/06/08 06:11

mutex (互斥量)

        多个线程同时访问共享数据时可能会冲突,比如 两个线程都要把某个全局变量增加 1,这个操作在某平台需要三条指令完成:

1. 从内存读变量值到寄存器

2. 寄存器的值加1

3. 将寄存器的值写回内存

         对于多线程的程序,访问冲突的问题是很普遍的,解决的办法是引入互斥锁(Mutex,Mutual Exclusive Lock),获得锁的线程可以完成“读-修改-写”的操作,然后释放锁给其它线程,没有获得锁的线程只能等待而不能访问共享数据,这样“读-修改-写”三步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其它处理器上并行做这个操作。

pthread_mutex_init  函数对 Mutex 做初始化,参数 attr 设定 Mutex 的属性,如果 attr 为 NULL 则表示缺省属性,pthread_mutex_init 函 数初始化的 Mutex 可以用pthread_mutex_destroy 销毁。如果 Mutex 变量是静态分配的(全局变量 或 static 变量),也可以用宏定义 PTHREAD_MUTEX_INITIALIZER 来初始化,相当于用pthread_mutex_init 初始化并且 attr 参数为 NULL。Mutex 的加锁和解锁返回值:成功返回0,失败返回错误号。

        一个线程可以调用 pthread_mutex_lock 获得 Mutex,如果这时另一个线程已经调用 pthread_mutex_lock 获得了该 Mutex,则当前线程需要挂起等待,直到另一个线程调用pthread_mutex_unlock 释放 Mutex,当前线程被唤醒,才能获得该 Mutex 并继续执行。
        如果一个线程既想获得锁,又不想挂起等待,可以调用 pthread_mutex_trylock,如果 Mutex 已经被另一个线程获得,这个函数会失败返回 EBUSY,而不会使线程挂起等待。

        为了实现互斥锁操作,大多数体系结构都提供了swap 或 exchange 指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性,即使是多处理器平台,访问内存的总线周期也有先后,一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期。

下面我们举例来证明一下:

代码如下:








运行结果:



        从上面的例子可以看出,在不加互斥锁的情况下,会出现生产者一直生产或者消费者一直消费的情况,而当我们加入了互斥锁以后,就会形成一一对应的关系,即生产者生产一个消费者消费一个的情况,这样就避免了某个线程一直挂起等待的情况。




原创粉丝点击