返回

iOS底层分析-锁(二)

IOS

synchronized中SyncData的结构

我们先来看一下SyncData,它的结构如下:

struct SyncData {
    pthread_mutex_t mutex;
    long spinlock;
    struct pthread_cond cond;
};
  • mutex:这是一个pthread_mutex_t类型的变量,它是一个互斥锁。
  • spinlock:这是一个long类型的变量,它是一个自旋锁。
  • cond:这是一个pthread_cond_t类型的变量,它是一个条件变量。

mutex

mutex是一个互斥锁,它可以保证只有一个线程可以同时访问临界区。当一个线程进入临界区时,它会获得互斥锁,其他线程将被阻塞,直到该线程释放互斥锁。

spinlock

spinlock是一个自旋锁,它与互斥锁类似,但它不会阻塞线程。当一个线程试图获取自旋锁时,如果自旋锁已经被另一个线程持有,它将自旋等待,直到自旋锁被释放。

cond

cond是一个条件变量,它可以用来通知线程某个条件已经满足。当一个线程等待某个条件满足时,它可以调用pthread_cond_wait()函数,该函数将使线程进入睡眠状态,直到条件满足。当另一个线程调用pthread_cond_signal()函数时,它将唤醒所有正在等待该条件的线程。

SyncData的用法

SyncData结构用于实现synchronized。当一个线程进入synchronized块时,它会先获取SyncData结构中的互斥锁,然后才能访问临界区。当线程离开synchronized块时,它会释放互斥锁。

如果一个线程试图获取SyncData结构中的互斥锁,但互斥锁已经被另一个线程持有,它将自旋等待,直到互斥锁被释放。

如果一个线程在等待SyncData结构中的条件变量时,另一个线程调用了pthread_cond_signal()函数,那么该线程将被唤醒。

示例代码

@synchronized(self) {
    // 临界区代码
}

上面的代码是一个synchronized块,它使用self作为锁对象。当一个线程进入synchronized块时,它会先获取self对象的互斥锁,然后才能访问临界区。当线程离开synchronized块时,它会释放互斥锁。

如果一个线程试图获取self对象的互斥锁,但互斥锁已经被另一个线程持有,它将自旋等待,直到互斥锁被释放。

如果一个线程在等待self对象的条件变量时,另一个线程调用了pthread_cond_signal()函数,那么该线程将被唤醒。

总结

SyncData结构用于实现synchronized关键字。它包含一个互斥锁、一个自旋锁和一个条件变量。互斥锁用于保证只有一个线程可以同时访问临界区。自旋锁用于减少线程在等待互斥锁时的时间开销。条件变量用于通知线程某个条件已经满足。