0

0

嵌入式Linux:线程同步(自旋锁)

蓮花仙者

蓮花仙者

发布时间:2025-04-18 08:20:01

|

889人浏览过

|

来源于php中文网

原创

linux自旋锁(spinlock)是一种用于保护共享资源的锁机制,主要应用于多核处理器环境中。当一个核或线程尝试获取锁时,如果发现锁已被其他核持有,它会持续忙等(不断循环检查),而不是让出cpu时间片。

嵌入式Linux:线程同步(自旋锁)

自旋锁的特点是适用于锁的持有时间极短的场景,因为它在等待期间不会主动放弃CPU,而是不断尝试获取锁,这在多核系统中可以避免由于线程调度带来的上下文切换开销。

工作原理:

加锁:线程尝试获取锁,如果成功,则进入临界区。如果锁已被占用,线程会不停地轮询检查锁是否释放。

忙等(自旋):如果锁被占用,线程会持续忙等,不会主动让出CPU。这样避免了上下文切换,但消耗了CPU资源,因此自旋锁适用于锁定时间较短的场景。

解锁:当临界区的任务完成后,线程释放锁,其他正在忙等的线程可以继续尝试获取锁。

自旋锁常用于以下情况:

  • 需要保护的代码段执行时间非常短,能够迅速释放锁。
  • 不希望线程进入睡眠状态或导致上下文切换,尤其是在内核中的中断处理程序或者性能要求高的系统。
  • 多核系统中,并发访问的共享资源保护,避免线程在上下文切换中浪费时间。

自旋锁与互斥锁的比较如下:

实现方式上的区别

自旋锁是一种轻量级锁机制,它在忙等状态下获取锁。当线程无法获取锁时,不会进入睡眠或等待状态,而是会不断检查锁的状态,直到可以成功获取锁。互斥锁则是一种更高层的锁,通常在无法获取锁时会导致线程进入阻塞状态。互斥锁可以让操作系统将当前线程挂起,等待锁可用时再唤醒。

开销上的区别:

自旋锁的主要优势在于没有上下文切换的开销,特别适用于锁持有时间很短的场景。由于自旋锁不会导致线程休眠,所以在处理器繁忙时可能会浪费CPU时间。如果等待时间较长,忙等会消耗过多的CPU资源,反而导致效率下降。互斥锁的开销较大,因为线程在获取不到锁时会陷入休眠,直到获取到锁时才会被唤醒。休眠和唤醒的代价很高,特别是在频繁锁定/解锁的场景中会影响性能。

适用场景上的区别:

自旋锁常用于内核中或者需要避免上下文切换的场景。特别是在中断上下文中,自旋锁更为合适,因为中断处理程序不能被阻塞或休眠。它适用于那些执行时间极短的临界区,锁的持有时间必须足够短,才能避免因自旋导致CPU资源浪费。互斥锁更适用于用户态的程序或者锁定时间较长的临界区。当程序无法获取到互斥锁时,系统可以调度其他线程运行,直到锁被释放,适合长时间的等待操作。

死锁问题:

如果对同一个自旋锁进行两次加锁操作,必然会导致死锁,因为自旋锁不具备递归性。互斥锁则可以通过特定的类型来避免死锁。例如PTHREAD_MUTEX_ERRORCHECK类型的互斥锁在检测到重复加锁时,会返回错误而不是陷入死锁状态。

1、自旋锁初始化与销毁

自旋锁需要在使用前进行初始化,并在不再使用时销毁。

初始化自旋锁函数如下:

聚好用AI
聚好用AI

可免费AI绘图、AI音乐、AI视频创作,聚集全球顶级AI,一站式创意平台

下载
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);

参数:

  • lock:指向需要初始化的自旋锁对象。
  • pshared:自旋锁的共享属性,可以取值:
    • PTHREAD_PROCESS_SHARED:允许在多个进程中的线程之间共享自旋锁。
    • PTHREAD_PROCESS_PRIVATE:自旋锁只能在同一进程内的线程之间使用。

返回值:成功时返回0,失败时返回非零错误码。

销毁自旋锁函数如下:

int pthread_spin_destroy(pthread_spinlock_t *lock);

参数:lock:指向要销毁的自旋锁对象。

返回值:成功时返回0,失败时返回非零错误码。

2、自旋锁加锁与解锁

加锁函数如下:

int pthread_spin_lock(pthread_spinlock_t *lock);

参数:lock:指向要加锁的自旋锁对象。

返回值:成功时返回0;如果锁已经被其他线程占用,则线程会忙等,直到成功获取锁,最终返回0。

尝试加锁函数如下:

int pthread_spin_trylock(pthread_spinlock_t *lock);

参数:lock:指向要加锁的自旋锁对象。

返回值:

  • 成功时返回0。
  • 如果锁已被占用,立即返回EBUSY。

解锁函数如下:

int pthread_spin_unlock(pthread_spinlock_t *lock);

参数:lock:指向要解锁的自旋锁对象。

返回值:成功时返回0,失败时返回非零错误码。

下面是一个完整的示例,展示如何使用自旋锁,包括初始化、加锁、解锁和销毁:

pthread_spinlock_t spinlock; // 定义自旋锁
int shared_data = 0; // 共享数据

void *thread_func(void *arg) {
    pthread_spin_lock(&spinlock); // 加锁
    shared_data++;
    printf("Thread %ld: shared_data = %d\n", (long)arg, shared_data);
    pthread_spin_unlock(&spinlock); // 解锁
    return NULL;
}

int main() {
    pthread_t threads[2];
    // 初始化自旋锁
    if (pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE) != 0) {
        perror("Failed to initialize spinlock");
        return 1;
    }
    // 创建两个线程
    pthread_create(&threads[0], NULL, thread_func, (void *)1);
    pthread_create(&threads[1], NULL, thread_func, (void *)2);
    // 等待线程结束
    pthread_join(threads[0], NULL);
    pthread_join(threads[1], NULL);
    // 销毁自旋锁
    if (pthread_spin_destroy(&spinlock) != 0) {
        perror("Failed to destroy spinlock");
        return 1;
    }
    return 0;
}

自旋锁的主要问题在于,它在获取不到锁时不会释放CPU,而是持续消耗资源。如果锁持有时间较长,CPU的利用效率会急剧下降。因此,自旋锁不适合用于长时间锁定的场景,只适合那些临界区极短的操作。

通过对pthreadspin*函数的合理使用,可以有效管理多线程访问共享资源的同步问题。确保在适当的地方进行加锁和解锁,以防止死锁和资源竞争。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

466

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

63

2025.12.24

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1344

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

698

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

293

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

772

2023.07.05

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

571

2023.07.06

linux查看文件夹大小
linux查看文件夹大小

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。linux怎么查看文件夹大小呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

544

2023.07.20

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Node.js 教程
Node.js 教程

共57课时 | 7.5万人学习

CSS3 教程
CSS3 教程

共18课时 | 4.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号