可重入锁的学习

java和Go在可重入锁上的对比

面试提到有关go是如何实现可重入锁的,都不太记得go有这个,记录下

  1. 可重入锁的概念:指的是同一个线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。

  2. java的可重入锁:Java直接展示结果,是可以运行的,类似的代码结构在golang中会出现 竞争异常(java的synchronized也是可重入结构)
    在这里插入图片描述

  3. go的锁是否是可重入的

    type Reentrant struct {
    	sync.Mutex
    
    }
    
    func (receiver *Reentrant) methodA()  {
    	receiver.Lock()
    	fmt.Println("method A is running")
    	receiver.methodB()
    
    	receiver.Unlock()
    }
    
    func (receiver Reentrant) methodB()  {
    	receiver.Lock()
    	fmt.Println("method B is running")
    	receiver.Unlock()
    }
    
    func TestReentrant(t *testing.T) {
    	a := new(Reentrant)
    	a.methodA()
    }
    

    在这里插入图片描述

  4. go实习一个简单的可重入锁
    关于可重入锁的原理,需要存储的信息包括锁定状态(需要注意状态设置的原子性),持有锁的线程,以及重入的次数,其中针对go来说获取线程编号存在问题

    	import (
    	"fmt"
    	"runtime"
    	"strconv"
    	"strings"
    	"sync"
    	"sync/atomic"
    )
    
    type MyReentrantLock struct {
    	lock sync.Mutex
    	id int
    	counter int32
    }
    
    func (l *MyReentrantLock) Lock()  {
    
    	// 第一次锁
    	if atomic.CompareAndSwapInt32(&(l.counter), 0, 1){
    		l.lock.Lock()
    		l.id = GoID()
    	}else {
    		if GoID() == l.id{
    			atomic.AddInt32(&(l.counter), 1)
    		}else {
    			// 这里就是阻塞goroutine了
    			l.lock.Lock()
    		}
    	}
    
    
    
    
    
    }
    
    func (l *MyReentrantLock) Unlock()  {
    	// 当counter归零是真正释放锁
    	v := atomic.LoadInt32(&(l.counter))
    	if v == 0{
    		panic("this mutex is not locked")
    	}
    	if l.id == GoID(){
    		v := atomic.AddInt32(&(l.counter), -1)
    		if v == 0 {
    			l.lock.Unlock()
    		}
    	}
    }
    
    func GoID() int {
    	var buf [64]byte
    	n := runtime.Stack(buf[:], false)
    	idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
    	id, err := strconv.Atoi(idField)
    	if err != nil {
    		panic(fmt.Sprintf("cannot get goroutine id: %v", err))
    	}
    	return id
    }
    
参考链接
  1. 对可重入锁和不可重入锁的理解,他们的区别及实现原理解析
  2. 如何获取goroutine id
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值