Go Mutex加锁流程笔记

Go Mutex加锁流程笔记

Mutex是一种基于CAS的自旋锁

获取锁——步骤
  • (1)协程调用Lock()函数。

  • (2)判断这个锁是否未初始化,如果该锁没有初始化,则对该锁进行初始化设置,然后获取锁,Lock()函数返回。如果该锁已被初始化过,则进入下一步操作。

  • (3)判断锁与协程的当前状态,如果该锁处于加锁状态且当前协程不处于饥饿状态,则尝试获取该锁的协程会进入自旋状态(最多自旋4次)。

  • (4)自旋完成后,计算当前锁的状态,协程尝试获取锁,如果获取成功,Lock()函数返回。如果获取失败,则进入下一步操作。

  • (5)自旋完成后尝试获取锁失败,该协程进入休眠状态,协程进入阻塞状态,并不断尝试获取信号。

  • (6)休眠协程获取到信号(有其他协程释放了锁),被唤醒,此时go会判断当前协程是否处于饥饿状态(如果协程从调用Lock()函数起,超过1ms后都没有成功获取到锁,则该协程进入饥饿状态)。如果该协程处于饥饿状态,不会启动自旋过程,而是再次被阻塞,一旦有其他的协程释放了锁,那么该饥饿协程就会被唤醒并直接获取锁,Lock()函数返回。如果该协程处于正常状态,则进入下一步操作。

  • (7)如果协程被判定处于正常状态,即满足再次启动自旋条件(协程从调用Lock()函数起到现在被唤醒的总时间不超过1ms),则重置自旋次数,再次启动自旋,尝试获取锁。如果自旋结束后,该协程还是没有获取到锁,则回到步骤(3),开始新一轮循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux中,如果一个线程或进程尝试对同一个互斥量进行两次锁定操作,就会出现死锁的情况。这是因为互斥量是一种用于保护共享资源的同步机制,它确保同一时间只有一个线程可以访问被保护的代码段或数据。 当一个线程已经持有了互斥量的锁,并且尝试再次对其进行加锁时,它将会被阻塞,直到其他线程释放了该互斥量的锁。然而,如果同一个线程在持有锁的情况下又尝试对互斥量加锁,就会导致死锁。 为了避免这种情况的发生,在使用互斥量进行加锁操作前,可以使用条件判断语句(如if语句)来判断当前线程是否已经持有了锁。只有在未持有锁的情况下才进行加锁操作。这样可以确保同一个线程不会多次加锁同一个互斥量。 以下是一个示例代码片段,展示了如何使用互斥量进行加锁,并避免多次加锁的情况: ```c #include <stdio.h> #include <pthread.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void* thread_function(void* arg) { // 加锁前进行条件判断,避免多次加锁 if (pthread_mutex_trylock(&mutex) == 0) { // 临界区代码 printf("Thread acquired lock.\n"); // 解锁 pthread_mutex_unlock(&mutex); } else { printf("Thread failed to acquire lock.\n"); } return NULL; } int main() { pthread_t thread; // 创建线程 pthread_create(&thread, NULL, thread_function, NULL); // 等待线程结束 pthread_join(thread, NULL); return 0; } ``` 在上述示例中,我们使用`pthread_mutex_trylock`函数进行加锁操作。如果加锁成功(返回值为0),则进入临界区代码并在操作完成后解锁。如果加锁失败,则输出相应的错误信息。 请注意,以上只是一种可能的处理方式,具体的实现方式可能因使用的编程语言和应用场景而有所不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值