写点什么

Linux 系统编程 -(pthread) 线程通信 (自旋锁)

作者:DS小龙哥
  • 2022 年 2 月 12 日
  • 本文字数:1479 字

    阅读完需:约 5 分钟

1. 自旋锁介绍

自旋锁不管是内核编程,还是应用层编程都会用到;自旋锁和互斥量类似,它不是通过休眠使进程阻塞,而是在获取锁之前一直处于忙等(也就叫自旋)状态。


自旋锁可用于下面的情况:锁被持有的时间短,并且线程不希望再重新调度上花费太多的成本。自旋锁通常作为底层原语用于实现其他类型的锁。根据他们所基于的系统架构,可以通过使用测试并设置指令有效地实现。当然这里说的有效也还是会导致 CPU 资源的浪费:当线程自旋锁变为可用时,CPU 不能做其他任何事情,这也是自旋锁只能够被只有一小段时间的原因。


自旋锁总结:

  1. 自旋锁和互斥锁的使用框架、场景相似的。

  2. 互斥锁在得不到锁的时候会休眠。

  3. 自旋锁在得不到锁的时候不会休眠,会一直检测锁的状态。

  4. 自旋锁比较适合保护变量赋值、函数调用等场景。

2. 自旋锁相关接口函数

1. 销毁自旋锁int   pthread_spin_destroy(pthread_spinlock_t *);2. 初始化自旋锁int   pthread_spin_init(pthread_spinlock_t *, int);3. 自旋锁上锁(阻塞)int   pthread_spin_lock(pthread_spinlock_t *);4. 自旋锁上锁(非阻塞)int   pthread_spin_trylock(pthread_spinlock_t *);5. 自旋锁解锁int   pthread_spin_unlock(pthread_spinlock_t *);以上函数成功都返回0.
复制代码


pthread_spin_init 函数的pshared参数表示进程共享属性,表明自旋锁是如何获取的,如果它设为PTHREAD_PROCESS_SHARED,则自旋锁能被,可以访问锁底层内存的线程所获取,即使那些线程属于不同的进程。否则pshared参数设为PTHREAD_PROCESS_PRIVATE,自旋锁就只能被初始化该锁的进程内部的线程访问到。


如果自旋锁当前在解锁状态,pthread_spin_lock函数不要自旋就可以对它加锁,试图对没有加锁的自旋锁进行解锁,结果是未定义的。需要注意,不要在持有自旋锁情况下可能会进入休眠状态的函数,如果调用了这些函数,会浪费 CPU 资源,其他线程需要获取自旋锁需要等待的时间更长了。

3. 自旋锁运用模板

下面代码创建了两个线程,分别访问一个全局变量,这里采用自旋锁进行保护。

#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <dirent.h>#include <stdlib.h>#include <pthread.h>
pthread_spinlock_t spinlock;
int data;/*线程工作函数*/void *thread_work_func(void *dev){ while(1) { pthread_spin_lock(&spinlock); //上锁 printf("data=%d\n",data); pthread_spin_unlock(&spinlock); //解锁 sleep(1); }}
/*线程工作函数*/void *thread_work_func2(void *dev){ while(1) { pthread_spin_lock(&spinlock); //上锁 data++; pthread_spin_unlock(&spinlock); //解锁 sleep(1); }}
int main(int argc,char **argv){ //初始化自旋锁 pthread_spin_init(&spinlock,PTHREAD_PROCESS_PRIVATE);
/*1. 创建子线程1*/ pthread_t thread_id; if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0) { printf("子线程1创建失败.\n"); return -1; } /*2. 创建子线程2*/ pthread_t thread_id2; if(pthread_create(&thread_id2,NULL,thread_work_func2,NULL)!=0) { printf("子线程2创建失败.\n"); return -1; }
/*3. 等待线程的介绍*/ pthread_join(thread_id,NULL); pthread_join(thread_id2,NULL);
//销毁自旋锁 pthread_spin_destroy(&spinlock); return 0;}
复制代码


发布于: 刚刚阅读数: 2
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
Linux系统编程-(pthread)线程通信(自旋锁)