linux下的线程及同步机制(2)

来源:互联网 发布:windows airplay 推送 编辑:程序博客网 时间:2024/06/05 03:01

2.1 Mutex

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



Mutex用pthread_mutex_t类型的变量表示,可以这样初始化和销毁:

#include <pthread.h>int pthread_mutex_destroy(pthread_mutex_t *mutex);int pthread_mutex_init(pthread_mutex_t *restrict mutex,       const pthread_mutexattr_t *restrict attr);pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

返回值:成功返回0,失败返回错误号。

pthread_mutex_init函数对Mutex做初始化,参数attr设定Mutex的属性,如果attrNULL则表示缺省属性。用pthread_mutex_init函数初始化的Mutex可以用pthread_mutex_destroy销毁。如果Mutex变量是静态分配的(全局变量或static变量),也可以用宏定义PTHREAD_MUTEX_INITIALIZER来初始化,相当于用pthread_mutex_init初始化并且attr参数为NULL。Mutex的加锁和解锁操作可以用下列函数:

#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);

返回值:成功返回0,失败返回错误号。

一个线程可以调用pthread_mutex_lock获得Mutex,如果这时另一个线程已经调用pthread_mutex_lock获得了该Mutex,则当前线程需要挂起等待,直到另一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能获得该Mutex并继续执行。

如果一个线程既想获得锁,又不想挂起等待,可以调用pthread_mutex_trylock,如果Mutex已经被另一个线程获得,这个函数会失败返回EBUSY,而不会使线程挂起等待。


 范例:

#include <stdio.h>#include <stdlib.h>#include <pthread.h>#define LOOP 5000int counter;pthread_mutex_t counter_mutex=PTHREAD_MUTEX_INITIALIZER;void *doit(void *p);int main(void){pthread_t tida,tidb;pthread_create(&tida,NULL,doit,NULL);pthread_create(&tidb,NULL,doit,NULL);pthread_join(tida,NULL);printf("hahadsj;fj;salfj;salfj");pthread_join(tidb,NULL);return 0;}void *doit(void *p){int i,val;for(i=0;i<LOOP;i++){pthread_mutex_lock(&counter_mutex);val=counter;printf("%x:%d\n",(unsigned int)pthread_self(),val+1);counter=val+1;10000pthread_mutex_unlock(&counter_mutex);}return NULL;}

最后的执行结果是:

10000

每个Mutex有一个等待队列,一个线程要在Mutex上挂起等待,首先在把自己加入等待队列中,然后置线程状态为睡眠,然后调用调度器函数切换到别的线程。一个线程要唤醒等待队列中的其它线程,只需从等待队列中取出一项,把它的状态从睡眠改为就绪,加入就绪队列,那么下次调度器函数执行时就有可能切换到被唤醒的线程。


原创粉丝点击