聊聊高并发(六)实现几种自旋锁(一)

聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响 我们了解了处理器缓存一致性协议的原理,并且提到了它对并发编程的影响,“多个线程对同一个变量一直使用CAS操作,那么会有大量修改操作,从而产生大量的缓存一致性流量,因为每一次CAS操作都会发出广播通知其他处理器,从而影响程序的性能。”


这一篇我们通过两种实现自旋锁的方式来看一下不同的编程方式带来的程序性能的变化。


先理解一下什么是自旋,所谓自旋就是线程在不满足某种条件的情况下,一直循环做某个动作。所以对于自旋锁来锁,当线程在没有获取锁的情况下,一直循环尝试获取锁,直到真正获取锁。


聊聊高并发(三)锁的一些基本概念 我们提到锁的本质就是等待,那么如何等待呢,有两种方式

1. 线程阻塞

2. 线程自旋


阻塞的缺点显而易见,线程一旦进入阻塞(Block),再被唤醒的代价比较高,性能较差。自旋的优点是线程还是Runnable的,只是在执行空代码。当然一直自旋也会白白消耗计算资源,所以常见的做法是先自旋一段时间,还没拿到锁就进入阻塞。JVM在处理synchrized实现时就是采用了这种折中的方案,并提供了调节自旋的参数。


这篇说一下两种最基本的自旋锁实现,并提供了一种优化的锁,后续会有更多的自旋锁的实现。


首先是TASLock (Test And Set Lock),测试-设置锁,它的特点是自旋时,每次尝试获取锁时,采用了CAS操作,不断的设置锁标志位,当锁标志位可用时,一个线程拿到锁,其他线程继续自旋。

缺点是CAS操作一直在修改共享变量的值,会引发缓存一致性流量风暴

package com.test.lock;

// 锁接口
public interface Lock {
    public 
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
首先,需要定义一个全局变量`lock`和一个自旋锁的结构体: ```c int lock = 0; typedef struct spinlock { int locked; } spinlock_t; ``` 然后,使用`lock bts`指令实现自旋锁的`lock`和`unlock`操作: ```c void spin_lock(spinlock_t *lock) { while (__sync_lock_test_and_set(&lock->locked, 1)) { while (lock->locked) { __asm__ volatile ("pause\n"); } } } void spin_unlock(spinlock_t *lock) { __sync_lock_release(&lock->locked); } ``` 在`spin_lock`函数中,使用`__sync_lock_test_and_set`原子操作将`lock->locked`设置为1,并返回原来的值。如果返回的值为1,说明自旋锁已经被其他线程持有,此时进入内层循环,等待其他线程释放自旋锁。在内层循环中,使用`pause`指令让CPU进入低功耗状态,减少空转对CPU资源的占用。 在`spin_unlock`函数中,使用`__sync_lock_release`原子操作将`lock->locked`设置为0,释放自旋锁。 完整的代码如下: ```c #include <stdio.h> #include <stdlib.h> int lock = 0; typedef struct spinlock { int locked; } spinlock_t; void spin_lock(spinlock_t *lock) { while (__sync_lock_test_and_set(&lock->locked, 1)) { while (lock->locked) { __asm__ volatile ("pause\n"); } } } void spin_unlock(spinlock_t *lock) { __sync_lock_release(&lock->locked); } void *thread_func(void *arg) { spinlock_t *lock = (spinlock_t *)arg; spin_lock(lock); printf("Thread %ld acquired lock\n", pthread_self()); sleep(1); spin_unlock(lock); printf("Thread %ld released lock\n", pthread_self()); return NULL; } int main(int argc, char **argv) { spinlock_t lock = {0}; pthread_t threads[4]; for (int i = 0; i < 4; i++) { pthread_create(&threads[i], NULL, thread_func, &lock); } for (int i = 0; i < 4; i++) { pthread_join(threads[i], NULL); } return 0; } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值