当前位置: 首页 > news >正文

iOS - 原子操作

在 Objective-C 运行时中,原子操作主要通过以下几种方式实现:

1. 基本原子操作

// 原子操作的基本实现
#if __has_feature(c_atomic)#define OSAtomicIncrement32(p)        __c11_atomic_add((_Atomic(int32_t) *)(p), 1, __ATOMIC_RELAXED)
#define OSAtomicDecrement32(p)        __c11_atomic_sub((_Atomic(int32_t) *)(p), 1, __ATOMIC_RELAXED)
#define OSAtomicIncrement32Barrier(p) __c11_atomic_add((_Atomic(int32_t) *)(p), 1, __ATOMIC_SEQ_CST)
#define OSAtomicDecrement32Barrier(p) __c11_atomic_sub((_Atomic(int32_t) *)(p), 1, __ATOMIC_SEQ_CST)#else// 使用内联汇编实现原子操作
static ALWAYS_INLINE int32_t 
OSAtomicIncrement32(volatile int32_t *value) {return __sync_fetch_and_add(value, 1) + 1;
}static ALWAYS_INLINE int32_t 
OSAtomicDecrement32(volatile int32_t *value) {return __sync_fetch_and_sub(value, 1) - 1;
}#endif

2. 自旋锁实现

typedef struct {volatile int32_t value;
} OSSpinLock;// 自旋锁的原子操作
static ALWAYS_INLINE void
OSSpinLockLock(volatile OSSpinLock *lock)
{do {while (lock->value != 0) {// 忙等待__asm__ volatile ("pause");}} while (!OSAtomicCompareAndSwap32(0, 1, &lock->value));
}static ALWAYS_INLINE bool
OSSpinLockTry(volatile OSSpinLock *lock)
{return OSAtomicCompareAndSwap32(0, 1, &lock->value);
}static ALWAYS_INLINE void
OSSpinLockUnlock(volatile OSSpinLock *lock)
{OSAtomicAnd32Barrier(0, &lock->value);
}

3. 比较和交换操作

// 原子比较和交换操作
static ALWAYS_INLINE bool
OSAtomicCompareAndSwapPtr(void *oldp, void *newp, void *volatile *dst)
{return __sync_bool_compare_and_swap(dst, oldp, newp);
}static ALWAYS_INLINE bool
OSAtomicCompareAndSwapLong(long oldl, long newl, volatile long *dst)
{return __sync_bool_compare_and_swap(dst, oldl, newl);
}static ALWAYS_INLINE bool
OSAtomicCompareAndSwap32(int32_t old, int32_t new, volatile int32_t *dst)
{return __sync_bool_compare_and_swap(dst, old, new);
}

4. 内存屏障

// 内存屏障实现
#define OSMemoryBarrier()  __sync_synchronize()static ALWAYS_INLINE void
OSMemoryBarrierBeforeUnlock()
{
#if defined(__arm__) || defined(__arm64__)OSMemoryBarrier();
#endif
}

5. 原子引用计数操作

inline bool 
objc_object::rootTryRetain()
{return sidetable_tryRetain() || rootRetain_overflow(true);
}inline bool 
objc_object::sidetable_tryRetain()
{SideTable& table = SideTables()[this];bool result = false;table.lock();RefcountMap::iterator it = table.refcnts.find(this);if (it != table.refcnts.end()) {RefcountMap::value_type &pair = *it;if (pair.second & SIDE_TABLE_RC_PINNED) {pair.second += SIDE_TABLE_RC_ONE;result = true;}else if (pair.second & SIDE_TABLE_RC_WEAKLY_REFERENCED) {pair.second = SIDE_TABLE_RC_ONE | SIDE_TABLE_RC_WEAKLY_REFERENCED;result = true;}}table.unlock();return result;
}

6. 原子属性访问器

// 原子属性的 getter
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {if (!atomic) return *((id *)((char *)self + offset));// 原子操作spinlock_t& slotlock = PropertyLocks[GOODHASH(offset)];slotlock.lock();id value = *((id *)((char *)self + offset));slotlock.unlock();return value;
}// 原子属性的 setter
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy) 
{if (!atomic) {*((id *)((char *)self + offset)) = newValue;return;}spinlock_t& slotlock = PropertyLocks[GOODHASH(offset)];slotlock.lock();*((id *)((char *)self + offset)) = newValue;slotlock.unlock();
}

7. 原子操作的使用场景

1. 引用计数管理

// 原子递增引用计数
id objc_retain(id obj) {if (!obj) return obj;if (obj->isTaggedPointer()) return obj;return obj->retain();
}

2. 属性访问

// 原子属性的实现
@property (atomic) NSString *name;

3. 数据结构操作

// 线程安全的数组操作
- (void)addObject:(id)object {@synchronized(self) {[_array addObject:object];}
}

这些原子操作的实现保证了:

  • 原子性:操作要么完全执行,要么完全不执行
  • 可见性:一个线程的修改对其他线程立即可见
  • 有序性:防止指令重排导致的问题

通过这些机制,Objective-C 运行时能够保证多线程环境下的数据一致性和线程安全。

http://www.lryc.cn/news/517264.html

相关文章:

  • Go语言的语法
  • 【MySQL 保姆级教学】用户管理和数据库权限(16)
  • 什么是 ES6 “模板语法” ?
  • [项目实战2]贪吃蛇游戏
  • 关于FPGA中添加FIR IP核(采用了GOWIN EDA)
  • 1. 使用springboot做一个音乐播放器软件项目【前期规划】
  • 【Dify】Dify自定义模型设置 | 对接DMXAPI使用打折 Openai GPT 或 Claude3.5系列模型方法详解
  • 【Rust自学】10.8. 生命周期 Pt.4:方法定义中的生命周期标注与静态生命周期
  • 121 买入股票的最佳时机
  • PID学习资料
  • 采用标准化的方式开展设计-研发中运用设计模式
  • 【Linux系列】并发与顺序执行:在 Linux 脚本中的应用与选择
  • Scala语言的数据库交互
  • 字节青训十五题-Java-数字字符串格式化
  • 搭建一个本地轻量级且好用的学习TypeScript语言的环境
  • apex安装
  • 会员制电商创新:开源 AI 智能名片与 2+1 链动模式的协同赋能
  • Vue 3 和 Electron 来构建一个桌面端应用
  • 生物医学信号处理--绪论
  • STM32之CAN通讯(十一)
  • 在macOS上安装MySQL
  • netty解码器LengthFieldBasedFrameDecoder用法详解
  • 在循环链表中用头指针和用尾指针的好处
  • java项目之网上租贸系统源码(springboot+mysql+vue)
  • 我用AI学Android Jetpack Compose之入门篇(3)
  • get和post有什么区别
  • 编排式 Saga 模式
  • QT 下拉菜单设置参数 起始端口/结束端口/线程数量 端口扫描4
  • 缓存-Redis-常见问题-缓存击穿-永不过期+逻辑过期(全面 易理解)
  • 137. 只出现一次的数字 II