当前位置: 首页 > 后端技术 > PHP

计算机操作系统基础(十二)---线程同步自旋锁

时间:2023-03-29 23:11:28 PHP

介绍本文为第十二篇,线程同步自旋锁。解决线程同步问题。本文是另一种解决线程同步的方法---自旋锁和自旋锁的工作原理与互斥完全一样。它还在访问关键资源之前加了一把锁,然后释放了锁。但是,互斥锁和自旋锁还是有一点区别的。自旋锁也是一个多线程的同步变量。使用自旋锁的线程会反复检查锁变量是否可用。如果不可用,会反复检查,所以自动自旋锁不会放弃CPU,是忙等待状态,所以自旋锁其实就是:无限循环等待锁被释放的好处自旋锁的自旋锁避免了进程或线程上下文切换的开销(如果锁花费的时间不是很长,代价还是很小的)操作系统中很多地方都使用自旋锁来代替互斥锁。自旋锁不适合单核CPU(因为自旋锁不释放CPU,如果用在单核CPU上,会导致其他进程或线程无法执行)自旋锁和互斥锁的比较(locks)自旋锁是非阻塞锁的一种,即如果一个线程需要Acquire一个自旋锁,但是这个锁已经被其他线程占用了,该线程不会被挂起,而是会继续消耗CPU时间,不断尝试获取自旋锁互斥量是阻塞锁,当一个线程无法获取到互斥量时,该线程将直接挂起,该线程将不再消耗CPU时间。当其他线程释放互斥锁时,操作系统会激活挂起的线程并投入运行。锁适用的场景如果是多核处理器,如果期望线程等待锁的时间很短,短到小于线程两次上下文切换的时间,则使用自旋锁是划算的。如果是多核处理器,如果预计线程等待锁的时间很长,至少比两次线程上下文切换的时间长。建议使用互斥锁。如果是单核处理器,一般建议不要使用自旋锁。因为同时只有一个线程处于运行状态,如果运行线程发现自己无法获取到锁,只能等待解锁,但是因为自己并没有挂起,已经获取到锁的线程已经没办法进入运行状态。等到正在运行的线程用完了操作系统分配给它的时间片,它才有机会被调度。在这种情况下,使用自旋锁的成本非常高。建议:如果加锁的代码经常被调用,但是很少发生竞争,应该优先使用自旋锁。自旋锁的开销比较小,mutex高开销自旋锁的代码示例#include#include#include#include$include//自旋锁定义pthread_spinlock_tspin_lock;//关键资源intnum=0;//Producervoid*producer(void*){inttimes=100000000;//循环一百万次while(times--){//添加自旋锁pthread_spin_lock(&spin_lock);num+=1;//每次生产一个产品//解锁pthread_spin_unlock(&spin_lock);}}//消费者void*consumer(void*){inttimes=100000000;while(times--){//添加自旋锁pthread_spin_lock(&spin_lock);num-=1;//一次消费一个产品//解锁pthread_spin_unlock(&spin_lock);}}intmain(){printf("从主函数开始。");//初始化自旋锁pthread_spin_init(&spin_lock,0);//定义两个线程pthread_tthread1,thread2;//一次执行生产者逻辑,一个执行消费者逻辑pthread_create(&thread1,NULL,&producer,NULL);pthread_create(&thread2,NULL,&consumer,NULL);pthread_join(&thread1,NULL);pthread_join(&thread2,NULL);//打印关键资源printf("在main函数中打印:num=%d\n",num);return0;}执行结果就是在瞬息万变的技术中找到相同点,这是一个技术人的核心竞争力。理论结合实践