38、iOS底层分析 - 线程锁(八)分类及其他补充

锁总结


 1、自旋锁

 线程反复检查锁变量是否可用,由于线程在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显示释放自旋锁,自旋锁避免了进程上下文的调度开销。因此对于线程只会阻塞很短时间的场合是有效的,而atomic 就是通过在 setter、getter 方法中添加自旋锁来实现线程安全的。


 2、互斥锁

互斥锁时用于多线程编程中,防止多条线程同时对统一公共资源进行读写访问的锁。通过将代码切成一个个的临界区而达成,就像加入一个线程在执行还没解锁,那当前线程就休息一会。自旋锁是忙等,互斥锁时获取不到锁就休眠,其他线程解锁后在唤醒继续执行。自旋锁效率更高,但是性能消耗也大。
 NSLock
 pthread_mutex
 @synchronized
 

 3、读写锁

读写锁是一种特殊的自旋锁,他把共享资源的访问者划分成读者和写者,读者只对公共资源进行访问,写者则需要对公共资源进行写操作
 这种锁对于自旋锁而言,能提高并发性,隐藏在多处理系统中,他允许同时多个读者访问共享资源,最大可能的读者数为实际的逻辑CPU数,写者是排他性的,一个读写锁同时只能有一个写者或多个读者,但不能同时有读者 和 写者,在读写锁保持期间也是抢占失效的。
 如果读写锁当前没有读者,也没有写者,那么写者可以立刻获得读写锁,否者他必须自选在那里,直到没有任何写者或读者。如果读写锁没有写者,那么读者可以立即获得该读写锁,否者读者必须自选在那里,直到写者释放该读写锁
 一次只能有一个线程可以占有写模式的读写锁,但是可以有多个线程同时占有读模式的读写锁。
    (1)、当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞
    (2)、当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是如果线程希望以写模式对此锁进行加锁,它必须等d所有的线程释放锁。
    (3)、通常当读写锁处于读模式锁住状态时,如果有另外线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,这样可以避免读模式锁长时间占用,而等待的写模式锁请求长时间阻塞。
    (4)、读写锁适合于对数据结构的读次数比写次数多得多的情况。因为,读模式锁定时可以共享,以写模式锁住时意味着独占,所以读写锁又叫  共享 - 独占锁

 读写锁实现

#pragma mark - 读数据
    - (id)lg_objectForKey:(NSString *)key{
        __block id obj;
        // 同步读取指定数据:
        dispatch_sync(self.concurrent_queue, ^{
            obj = [self.dataCenterDic objectForKey:key];
        });
        return obj;
    }
    
#pragma mark - 写数据
    - (void)lg_setObject:(id)obj forKey:(NSString *)key{
        // 异步栅栏调用设置数据:
        dispatch_barrier_async(self.concurrent_queue, ^{
            [self.dataCenterDic setObject:obj forKey:key];
        });
    }

我们可以创建一个并发队列,对于读操作,我们可以用同步函数进行处理,对于写操作我们可以用异步栅栏函数这操作,这样就简单实现了一个读写锁

互斥锁里 tls解释

 

 

发布了104 篇原创文章 · 获赞 13 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/shengdaVolleyball/article/details/105390072
今日推荐