完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在Linux系统里,有很多锁的应用,包括互斥锁,文件锁,读写锁等等,信号量其实也应该是锁的一种。使用锁的目的是为了达到进程、线程之间的同步作用,使共享资源在同一时间内,只有能有一个进程或者线程对它进行操作。在此处我们主要针对互斥锁(Mutex)进行介绍,互斥锁也是多线程间同步的主要方法之一。 互斥锁是通过一种简单的加锁方法来控制对共享资源的存取。这个互斥锁只有两种状态,也就是上锁和解锁。在同一时刻只能有一个掌握拥有上锁状态的线程能够对共享资源进行操作。若有线程希望访问共享资源,则该线程首先要给共享资源上互斥锁,以防止其它线程也同时对共享资源进行操作;若当前共享资源已经处于被其他线程上锁的状态的话,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。 互斥锁主要包括以下几个函数,分别是: 1. 互斥锁初始化函数pthread_mutex_init() 该函数初始化互斥锁变量mutex,其函数原型为: #includeint pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr); pthread_mutex_init()函数的第一个参数mutex是pthread_mutex_t互斥锁数据类型的指针。该互斥锁数据类型pthread_mutex_t在使用前要对其进行初始化,初始化的方法有以下两种: Ø 静态初始化:POSIX定义了一个宏PTHREAD_MUTEX_INItiALIZER结构常量来静态初始化互斥锁,只需要将互斥锁数据类型pthread_mutex_t定义的变量设置为PTHREAD_MUTEX_INITIALIZER即可。 Ø 动态初始化:在调用malloc()函数申请内存后。通过pthread_mutex_init()函数来动态初始化。在调用free()函数释放内存后需要调用pthread_mutex_destory()函数。 pthread_mutex_init()函数的第二参数mutexattr代表互斥锁的属性,通常采用默认的属性NULL即可。 pthread_mutex_init()函数调用成功返回0,否则返回-1。 2. 互斥锁加锁函数pthread_mutex_lock()和pthread_mutex_trylock() 这两个函数用来对互斥锁mutex执行加锁操作,其函数原型如下所示: #includeint pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); pthread_mutex_lock()函数是一个阻塞型的上锁函数,若互斥锁已经上了锁,调用pthread_mutex_lock()函数对互斥锁再次上锁的话,调用线程会阻塞,直到当前互斥锁被解锁。 pthread_mutex_trylock()函数是一个非阻塞型的上锁函数,如果互斥锁没被锁住,pthread_mutex_trylock()函数将把互斥锁加锁, 并获得对共享资源的访问权限;如果互斥锁被锁住了,pthread_mutex_trylock()函数将不会阻塞等待而直接返回EBUSY(已加锁错误),表示共享资源处于繁忙状态。 上述两个函数唯一的参数mutex是pthread_mutex_t数据类型的指针。该函数调用成功返回0,否则返回-1。 3. 互斥锁解锁函数pthread_mutex_unlock() 该函数用于解除mutex变量所指定的互斥锁,其函数原型如下所示: #includeint pthread_mutex_unlock(pthread_mutex_t *mutex); 如果互斥锁变量mutex已经上锁,调用pthread_mutex_unlock()函数将解除这个锁定,否则直接返回。该函数唯一的参数mutex是pthread_mutex_t数据类型的指针。该函数调用成功返回0,否则返回-1。 4. 消除互斥锁函数pthread_mutex_destory() 该函数用于清除mutex变量所指定的互斥锁,其函数原型如下所示: #includeint pthread_mutex_destory(pthread_mutex_t *mutex); 如果互斥锁变量mutex是采用动态初始化的话,调用malloc()函数申请内存后如果要释放内存则首先需要调用pthread_mutex_destory()函数清除pthread_mutex_t结构。该函数唯一的参数mutex是pthread_mutex_t数据类型的指针。该函数调用成功返回0,否则返回-1。 下面以一个互斥量代码mutex.c为例,介绍互斥量的使用方法,代码如下所示: #include #include #include #include#include #include #include #include pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; key_t key; int shmid,number; char i,*shms,*shmc; pid_t pid; static char msg[ ]="ABCDEFGHn"; int ret; void *thread_id1_handle(void *arg) { int i=0; while(1) { /*互斥锁上锁*/ if(pthread_mutex_lock(&mutex)!=0) { perror("pthread_mutex_lock"); } else printf("线程1:给共享内存加锁!n"); /* 建立共享内存 */ shms = (char *)shmat(shmid,0,0); printf("线程1:向共享内存写入数据!n"); /*父进程向共享内存中写入数据*/ memcpy(shms, msg, strlen(msg)+1); sleep(5); /*互斥锁解锁*/ if(pthread_mutex_unlock(&mutex)!=0) { perror("pthread_mutex_unlock"); } else printf("线程1:解锁共享内存!n"); printf("线程1:5秒钟后重新给共享内存加锁!n"); for(number=1;number<=5;number++) { printf("线程1:时间过去%d秒钟!n",number); sleep(1); } } } void *thread_id2_handle(void *arg) { while(1) { /*测试互斥锁*/ ret=pthread_mutex_trylock(&mutex); if(ret==EBUSY) printf("线程2:共享内存被线程1加锁n"); else { if(ret!=0) { perror("pthread_mutex_trylock"); exit(1); } else { printf("线程2:探测到线程1互斥锁解锁!n"); shmc = (char *)shmat(shmid,0,0); printf("线程2:读取共享内存的值为:%s",shmc); pthread_mutex_unlock(&mutex); } } sleep(1); } } int main(int argc, char *argv[ ]) { pthread_t thread_id1,thread_id2; key = ftok("/ipc/sem",'a'); shmid = shmget(key,1024,IPC_CREAT|0604); /*互斥锁初始化*/ pthread_mutex_init(&mutex,NULL); /*创建两个线程*/ pthread_create(&thread_id1,NULL,thread_id1_handle, NULL); pthread_create(&thread_id2,NULL,thread_id2_handle, NULL); pthread_join(thread_id1,NULL); pthread_join(thread_id2,NULL); exit(0); } 上述代码在主函数中创建了两个线程,并设置一段共享内存。在线程1主要完成共享内存的赋值以及互斥锁上锁和解锁工作,以此达到控制其他线程访问共享资源的目的,在给共享内存赋值之前对互斥锁加锁,赋值完毕后延时5秒钟,保证在这段时间内其他线程是无法访问到共享资源的,5秒钟后将互斥锁解锁并在延时5秒钟计数以让其它线程访问共享资源。线程2将一直访问有互斥锁的共享内存,当共享内存上锁后,利用pthread_mutex_trylock()函数将共享内存的互斥锁上锁情况打印出来,等到共享内存互斥锁解锁后将一直读取共享内存中的数据并打印。 编译mutex.c,因为该代码涉及到线程编程,因此在编译的时候还要添加编译选项“-lpthread”生成mutex可执行文件后并运行: # gcc -lpthread –o mutex mutex.c # ./mutex 代码运行效果如下图所示: 从代码的运行效果看出,线程1一开始就将共享内存加锁,线程2因无法访问共享内存而打印“共享内存对线程1加锁”的信息,之后线程1向共享内存中写入数据,线程2也一直无法访问共享内存,等到线程1将互斥锁解锁后,线程2才读取共享内存中的数据并打印。从图中线程2打印共享内存数据的次数可以看出,因线程1解锁互斥锁时间只有约5秒钟,而线程2读取共享内存的时间间隔约1秒钟,因此线程1解锁的时间里线程2只能访问5次共享内存并打印其中数据。之后上述过程再次循环直到用户强制代码停止运行。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4892 浏览 0 评论
87409 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4723 浏览 2 评论
3617 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2481 浏览 0 评论
1997浏览 3评论
1283浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1341浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1233浏览 0评论
1173浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 13:05 , Processed in 1.110863 second(s), Total 72, Slave 55 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号