最炫的网站,期货直播室网站建设,网络营销策划方案书,网站开发程序是什么个人主页#xff1a;C忠实粉丝 欢迎 点赞#x1f44d; 收藏✨ 留言✉ 加关注#x1f493;本文由 C忠实粉丝 原创 多线程 - 自旋锁 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记#xff0c;欢迎大家在评论区交流讨论#x1f48c; 目录 概述
原理
优点与… 个人主页C忠实粉丝 欢迎 点赞 收藏✨ 留言✉ 加关注本文由 C忠实粉丝 原创 多线程 - 自旋锁 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记欢迎大家在评论区交流讨论 目录 概述
原理
优点与缺点
优点
缺点
使用场景
自旋锁伪代码实现
Linux 提供的自旋锁系统调用
注意事项
结论
案例代码 概述
自旋锁是一种多线程同步机制用于保护共享资源免受并发访问的影响。在多个线程尝试获取锁时它们会持续自旋即在一个循环中不断检查锁是否可用而不是立即进入休眠状态等待锁的释放。这种机制减少了线程切换的开销适用于短时间内锁的竞争情况但是不合理的使用可能会造成 CPU 的浪费。
原理
自旋锁通常使用一个共享的标志位如一个布尔值来表示锁的状态。当标志位为 true 时表示锁已被某个线程占用当标志位为 false 时表示锁可用。当一个线程尝试获取自旋锁时它会不断检查标志位 1. 如果标志位为 false表示锁可用线程将设置标志位为 true表示自己占用了锁并进入临界区。 2. 如果标志位为 true即锁已被其他线程占用线程会在一个循环中不断自旋等待直到锁被释放。 优点与缺点
优点 1. 低延迟自旋锁使用于短时间内的锁竞争情况因为它不会让线程进入休眠状态从而避免了线程转换的开销提高了操作系统的效率。 2. 减少了系统调度开销 当多个线程同时自旋等待同一个锁时如果没有适当的退避策略可能会导致所有线程都在不断检查锁状态而无法进入临界区形成活锁。 缺点 1. CPU 资源浪费如果锁的持有时间较长等待获取锁的线程会一直循环等待导致 CPU 资源的浪费。 2. 可能引起活锁当多个线程同时自旋等待同一个锁时如果没有适当的退避策略可能会导致所有线程都在不断地检查锁状态而无法进入临界区形成活锁。 使用场景 1. 短暂等待地情况使用于锁被占用时间很短地场景如多线程对共享数据进行简单的读写操作。 2. 多线程的使用通常用于系统底层同步多个 CPU 对共享资源的访问。 自旋锁伪代码实现
自旋锁的实现通常使用原子操作来保证操作的原子性常用的软件实现方式是通过 CASCompare-And-Swap指令实现。以下是一个简单的自旋锁实现示例伪代码
#include stdio.h
#include stdatomic.h
#include pthread.h
#include unistd.h
// 使用原子标志来模拟自旋锁
atomic_flag spinlock ATOMIC_FLAG_INIT; // ATOMIC_FLAG_INIT 是0
// 尝试获取锁
void spinlock_lock()
{while (atomic_flag_test_and_set(spinlock)){// 如果锁被占用则忙等待}
}
// 释放锁
void spinlock_unlock()
{atomic_flag_clear(spinlock);
}
typedef _Atomic struct
{
#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1_Bool __val;
#elseunsigned char __val;
#endif
} atomic_flag; 功能描述 atomic_flag_test_and_set 函数检查 atomic_flag 的当前状态。如果 atomic_flag 之前没有被设置过即其值为 false 或 未设置 状态则函数会将其设置为 true或 设置 状态并返回先前的值在这种情况下为 false。如果 atomic_flag 之前已经被设置过即其值为 true则函数不会改变其状态但会返回 true。 原子性 这个操作是原子的意味着在多线程环境中它保证了对 atomic_flag 的读取和修改是不可分割的。当一个线程调用此函数时其他线程无法看到这个操作的任何中间状态这确保了操作的安全性。 Linux 提供的自旋锁系统调用
#include pthread.h
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);
注意事项 1. 在使用自旋锁时需要确保锁被释放的时间尽可能短以避免 CPU 资源的浪费。 2. 在多 CPU 环境下自旋锁可能不如其他锁机制高效因为它可能导致线程在不同的 CPU 上自旋等待。 结论 自旋锁是一种适用于短时间内竞争情况的同步机制它通过减少线程切换的开销来提高锁操作的效率。然而它存在 CPU 资源浪费和可能引起活锁等缺点。在使用自旋锁时需要根据具体的应用场景进行选择并确保锁被释放的时间尽可能短。 案例代码
// 操作共享变量会有问题的售票系统代码
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include pthread.hint ticket 1000;
pthread_spinlock_t lock;void *route(void *arg)
{char *id (char *)arg;while (1){pthread_spin_lock(lock);if (ticket 0){usleep(1000);printf(%s sells ticket:%d\n, id, ticket);ticket--;pthread_spin_unlock(lock);}else{pthread_spin_unlock(lock);break;}}return nullptr;
}int main(void)
{pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE);pthread_t t1, t2, t3, t4;pthread_create(t1, NULL, route, (void *)thread 1);pthread_create(t2, NULL, route, (void *)thread 2);pthread_create(t3, NULL, route, (void *)thread 3);pthread_create(t4, NULL, route, (void *)thread 4);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);pthread_spin_destroy(lock);return 0;
}