区块链技术博客
www.b2bchain.cn

如何知道一个锁到底被哪个线程占用(下)?求职学习资料

本文介绍了如何知道一个锁到底被哪个线程占用(下)?求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

  • 问题
  • 常用的锁
  • os_unfair_lock
    • 简单介绍
    • 追溯锁的拥有者

问题

在iOS开发调试的过程中,有时会发现app卡死了,点击 pause program execution暂停程序,会发现程序停到等待某个锁上面。如果程序停止在咱自己的代码上面还好排查一点。如果停在没有源码的第三方库或者系统库中,这就不好排查问题了。
这里有一个小方法,可能会提供一点帮助。那就是找到这个锁被那个线程占用了。

常用的锁

iOS中有很多锁,目前比较常用的有 pthread_mutexNSLockos_unfair_lock@synchronizeddispatch_semaphore。但不是所有的锁都能找到其被哪个线程所拥有。
目前我知道的能找到其拥有者的锁是 pthread_mutex_tos_unfair_lock以及基于这二者实现的其他上层 API,包括dispatch_onceNSLockNSRecursiveLock@synchronized
其中dispatch_once 的实现是基于 os_unfair_lock,剩下的实现是基于pthread_mutex_t

os_unfair_lock

简单介绍

os_unfair_lock 是一个低等级锁, 设计宗旨是用于替换 OSSpinLock,从 iOS 10 之后开始支持,跟 OSSpinLock 不同,等待 os_unfair_lock 的线程会处于休眠状态.
使用时首先要引入头文件#import

os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;//必须这么初始化 os_unfair_lock_lock(&lock);//加锁 //临界区 os_unfair_lock_unlock(&lock);//解锁

追溯锁的拥有者

os_unfair_lock 是一个结构体

typedef struct os_unfair_lock_s {     uint32_t _os_unfair_lock_opaque; } os_unfair_lock, *os_unfair_lock_t;

初始化就是把 _os_unfair_lock_opaque 赋值为零

(lldb) p _lock (os_unfair_lock) $0 = (_os_unfair_lock_opaque = 0)

执行加锁代码后再次查看

(lldb) p _lock (os_unfair_lock) $4 = (_os_unfair_lock_opaque = 4358)

(4358 的十六进制是0x1106)

从google上搜 os_unfair_lock_lock site:opensource.apple.com 能找到开源代码libplatform,我看的是220.100.1这一版

#ifndef __TSD_MACH_THREAD_SELF #define __TSD_MACH_THREAD_SELF 3 #endif static void _os_unfair_lock_lock_slow(_os_unfair_lock_t l, os_lock_owner_t self,         os_unfair_lock_options_t options) {     os_unfair_lock_options_t allow_anonymous_owner =             options & OS_UNFAIR_LOCK_ALLOW_ANONYMOUS_OWNER;     options &= ~OS_UNFAIR_LOCK_ALLOW_ANONYMOUS_OWNER;     if (unlikely(options & ~OS_UNFAIR_LOCK_OPTIONS_MASK)) {         __LIBPLATFORM_CLIENT_CRASH__(options, "Invalid options");     }     os_ulock_value_t current, new, waiters_mask = 0;      ......//删除了第一次加锁不会走到的代码      new = self & ~waiters_mask;     bool r = os_atomic_cmpxchgv2o(l, oul_value, OS_LOCK_NO_OWNER, new,             &current, acquire);     if (unlikely(!r)) goto _retry; }  void os_unfair_lock_lock(os_unfair_lock_t lock) {     _os_unfair_lock_t l = (_os_unfair_lock_t)lock;     os_lock_owner_t self = _os_lock_owner_get_self();     bool r = os_atomic_cmpxchg2o(l, oul_value, OS_LOCK_NO_OWNER, self, acquire);     if (likely(r)) return;     return _os_unfair_lock_lock_slow(l, self, OS_UNFAIR_LOCK_NONE); }  static inline os_lock_owner_t _os_lock_owner_get_self(void) {     os_lock_owner_t self;     self = (os_lock_owner_t)_os_tsd_get_direct(__TSD_MACH_THREAD_SELF);     return self; }

先把关注点放在 _os_lock_owner_get_self函数。
_os_tsd_get_direct也能找到源码,

static __inline__ void* _os_tsd_get_direct(unsigned long slot) {     void *ret;     __asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *))));     return ret; }

很幸运的是在开源代码 libpthread里发现了下面的代码

void * _pthread_getspecific_direct(unsigned long slot) { #if TARGET_IPHONE_SIMULATOR     return pthread_getspecific(slot); #else     return _os_tsd_get_direct(slot); #endif }

pthread_getspecific函数在咱引用 #import <pthread.h>后是可以调用的。

void * owner = pthread_getspecific(3);

做过实验后发现 owner & ~waiters_mask; 正好等于 _os_unfair_lock_opaque 的值。
现在就找到了os_unfair_lock与线程相关的值。
也可以看一下 os_unfair_lock_assert_owner 函数的源码,该函数是判断当前线程是否是 os_unfair_lock 的所有者,否则触发断言。
“`

  • 问题
  • 常用的锁
  • os_unfair_lock
    • 简单介绍
    • 追溯锁的拥有者

问题

在iOS开发调试的过程中,有时会发现app卡死了,点击 pause program execution暂停程序,会发现程序停到等待某个锁上面。如果程序停止在咱自己的代码上面还好排查一点。如果停在没有源码的第三方库或者系统库中,这就不好排查问题了。
这里有一个小方法,可能会提供一点帮助。那就是找到这个锁被那个线程占用了。

常用的锁

iOS中有很多锁,目前比较常用的有 pthread_mutexNSLockos_unfair_lock@synchronizeddispatch_semaphore。但不是所有的锁都能找到其被哪个线程所拥有。
目前我知道的能找到其拥有者的锁是 pthread_mutex_tos_unfair_lock以及基于这二者实现的其他上层 API,包括dispatch_onceNSLockNSRecursiveLock@synchronized
其中dispatch_once 的实现是基于 os_unfair_lock,剩下的实现是基于pthread_mutex_t

os_unfair_lock

简单介绍

os_unfair_lock 是一个低等级锁, 设计宗旨是用于替换 OSSpinLock,从 iOS 10 之后开始支持,跟 OSSpinLock 不同,等待 os_unfair_lock 的线程会处于休眠状态.
使用时首先要引入头文件#import

os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;//必须这么初始化 os_unfair_lock_lock(&lock);//加锁 //临界区 os_unfair_lock_unlock(&lock);//解锁

追溯锁的拥有者

os_unfair_lock 是一个结构体

typedef struct os_unfair_lock_s {     uint32_t _os_unfair_lock_opaque; } os_unfair_lock, *os_unfair_lock_t;

初始化就是把 _os_unfair_lock_opaque 赋值为零

(lldb) p _lock (os_unfair_lock) $0 = (_os_unfair_lock_opaque = 0)

执行加锁代码后再次查看

(lldb) p _lock (os_unfair_lock) $4 = (_os_unfair_lock_opaque = 4358)

(4358 的十六进制是0x1106)

从google上搜 os_unfair_lock_lock site:opensource.apple.com 能找到开源代码libplatform,我看的是220.100.1这一版

#ifndef __TSD_MACH_THREAD_SELF #define __TSD_MACH_THREAD_SELF 3 #endif static void _os_unfair_lock_lock_slow(_os_unfair_lock_t l, os_lock_owner_t self,         os_unfair_lock_options_t options) {     os_unfair_lock_options_t allow_anonymous_owner =             options & OS_UNFAIR_LOCK_ALLOW_ANONYMOUS_OWNER;     options &= ~OS_UNFAIR_LOCK_ALLOW_ANONYMOUS_OWNER;     if (unlikely(options & ~OS_UNFAIR_LOCK_OPTIONS_MASK)) {         __LIBPLATFORM_CLIENT_CRASH__(options, "Invalid options");     }     os_ulock_value_t current, new, waiters_mask = 0;      ......//删除了第一次加锁不会走到的代码      new = self & ~waiters_mask;     bool r = os_atomic_cmpxchgv2o(l, oul_value, OS_LOCK_NO_OWNER, new,             &current, acquire);     if (unlikely(!r)) goto _retry; }  void os_unfair_lock_lock(os_unfair_lock_t lock) {     _os_unfair_lock_t l = (_os_unfair_lock_t)lock;     os_lock_owner_t self = _os_lock_owner_get_self();     bool r = os_atomic_cmpxchg2o(l, oul_value, OS_LOCK_NO_OWNER, self, acquire);     if (likely(r)) return;     return _os_unfair_lock_lock_slow(l, self, OS_UNFAIR_LOCK_NONE); }  static inline os_lock_owner_t _os_lock_owner_get_self(void) {     os_lock_owner_t self;     self = (os_lock_owner_t)_os_tsd_get_direct(__TSD_MACH_THREAD_SELF);     return self; }

先把关注点放在 _os_lock_owner_get_self函数。
_os_tsd_get_direct也能找到源码,

static __inline__ void* _os_tsd_get_direct(unsigned long slot) {     void *ret;     __asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *))));     return ret; }

很幸运的是在开源代码 libpthread里发现了下面的代码

void * _pthread_getspecific_direct(unsigned long slot) { #if TARGET_IPHONE_SIMULATOR     return pthread_getspecific(slot); #else     return _os_tsd_get_direct(slot); #endif }

pthread_getspecific函数在咱引用 #import <pthread.h>后是可以调用的。

void * owner = pthread_getspecific(3);

做过实验后发现 owner & ~waiters_mask; 正好等于 _os_unfair_lock_opaque 的值。
现在就找到了os_unfair_lock与线程相关的值。
也可以看一下 os_unfair_lock_assert_owner 函数的源码,该函数是判断当前线程是否是 os_unfair_lock 的所有者,否则触发断言。
“`

  • 问题
  • 常用的锁
  • os_unfair_lock
    • 简单介绍
    • 追溯锁的拥有者

问题

在iOS开发调试的过程中,有时会发现app卡死了,点击 pause program execution暂停程序,会发现程序停到等待某个锁上面。如果程序停止在咱自己的代码上面还好排查一点。如果停在没有源码的第三方库或者系统库中,这就不好排查问题了。
这里有一个小方法,可能会提供一点帮助。那就是找到这个锁被那个线程占用了。

常用的锁

iOS中有很多锁,目前比较常用的有 pthread_mutexNSLockos_unfair_lock@synchronizeddispatch_semaphore。但不是所有的锁都能找到其被哪个线程所拥有。
目前我知道的能找到其拥有者的锁是 pthread_mutex_tos_unfair_lock以及基于这二者实现的其他上层 API,包括dispatch_onceNSLockNSRecursiveLock@synchronized
其中dispatch_once 的实现是基于 os_unfair_lock,剩下的实现是基于pthread_mutex_t

os_unfair_lock

简单介绍

os_unfair_lock 是一个低等级锁, 设计宗旨是用于替换 OSSpinLock,从 iOS 10 之后开始支持,跟 OSSpinLock 不同,等待 os_unfair_lock 的线程会处于休眠状态.
使用时首先要引入头文件#import

os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;//必须这么初始化 os_unfair_lock_lock(&lock);//加锁 //临界区 os_unfair_lock_unlock(&lock);//解锁

追溯锁的拥有者

os_unfair_lock 是一个结构体

typedef struct os_unfair_lock_s {     uint32_t _os_unfair_lock_opaque; } os_unfair_lock, *os_unfair_lock_t;

初始化就是把 _os_unfair_lock_opaque 赋值为零

(lldb) p _lock (os_unfair_lock) $0 = (_os_unfair_lock_opaque = 0)

执行加锁代码后再次查看

(lldb) p _lock (os_unfair_lock) $4 = (_os_unfair_lock_opaque = 4358)

(4358 的十六进制是0x1106)

从google上搜 os_unfair_lock_lock site:opensource.apple.com 能找到开源代码libplatform,我看的是220.100.1这一版

#ifndef __TSD_MACH_THREAD_SELF #define __TSD_MACH_THREAD_SELF 3 #endif static void _os_unfair_lock_lock_slow(_os_unfair_lock_t l, os_lock_owner_t self,         os_unfair_lock_options_t options) {     os_unfair_lock_options_t allow_anonymous_owner =             options & OS_UNFAIR_LOCK_ALLOW_ANONYMOUS_OWNER;     options &= ~OS_UNFAIR_LOCK_ALLOW_ANONYMOUS_OWNER;     if (unlikely(options & ~OS_UNFAIR_LOCK_OPTIONS_MASK)) {         __LIBPLATFORM_CLIENT_CRASH__(options, "Invalid options");     }     os_ulock_value_t current, new, waiters_mask = 0;      ......//删除了第一次加锁不会走到的代码      new = self & ~waiters_mask;     bool r = os_atomic_cmpxchgv2o(l, oul_value, OS_LOCK_NO_OWNER, new,             &current, acquire);     if (unlikely(!r)) goto _retry; }  void os_unfair_lock_lock(os_unfair_lock_t lock) {     _os_unfair_lock_t l = (_os_unfair_lock_t)lock;     os_lock_owner_t self = _os_lock_owner_get_self();     bool r = os_atomic_cmpxchg2o(l, oul_value, OS_LOCK_NO_OWNER, self, acquire);     if (likely(r)) return;     return _os_unfair_lock_lock_slow(l, self, OS_UNFAIR_LOCK_NONE); }  static inline os_lock_owner_t _os_lock_owner_get_self(void) {     os_lock_owner_t self;     self = (os_lock_owner_t)_os_tsd_get_direct(__TSD_MACH_THREAD_SELF);     return self; }

先把关注点放在 _os_lock_owner_get_self函数。
_os_tsd_get_direct也能找到源码,

static __inline__ void* _os_tsd_get_direct(unsigned long slot) {     void *ret;     __asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *))));     return ret; }

很幸运的是在开源代码 libpthread里发现了下面的代码

void * _pthread_getspecific_direct(unsigned long slot) { #if TARGET_IPHONE_SIMULATOR     return pthread_getspecific(slot); #else     return _os_tsd_get_direct(slot); #endif }

pthread_getspecific函数在咱引用 #import <pthread.h>后是可以调用的。

void * owner = pthread_getspecific(3);

做过实验后发现 owner & ~waiters_mask; 正好等于 _os_unfair_lock_opaque 的值。
现在就找到了os_unfair_lock与线程相关的值。
也可以看一下 os_unfair_lock_assert_owner 函数的源码,该函数是判断当前线程是否是 os_unfair_lock 的所有者,否则触发断言。
“`

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 如何知道一个锁到底被哪个线程占用(下)?求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们