线程安全

Posted The Ocean

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程安全相关的知识,希望对你有一定的参考价值。

    线程安全
        
        可重入/不可重入:针对函数,多个执行流中是否可以同时进入函数运行而不出现问题
        
        概念:指多个线程同时处理操作临界资源而不会出现数据二义性,则称是线程安全的            
            二义性:在线程中是否对临界资源进行了非原子操作
 
        如何实现线程安全:    
            同步(保证合理):临界资源的合理访问(时序可控)        
            互斥(保证安全):临界资源同一时间唯一访问
                
                如何实现互斥:(首先自身是安全的)
                    互斥锁:(黄牛抢票程序)
                        使用一个0/1的原子操作的计数器(图片):
                            1 -> 表示可以加锁,加锁就是计数-1 .
                            操作完毕后要解锁,解锁就是计数+1
                            0 -> 表示不可以加锁,不能加锁则等待
                            
                        操作步骤:
                            1.定义互斥锁变量    
                                pthread_mutex_t mutex;
                            2.初始化互斥锁变量    
                                int pthread_mutex_init()
                            3.加锁/解锁--->要在临界资源访问之前进行            
                                阻塞加锁,加不上锁就阻塞:
                                    int pthread_mutex_lock()
                                
                                非阻塞加锁,加不上则直接报错返回:                                    
                                    int pthread_mutex_trylock()
                            
                                限时阻塞加锁:
                                    int pthread_mutex_timedlock()
                                
                                *加锁之后要在线程任意有可能退出的地方解锁
                                
                                解锁:
                                    int pthread_mutex_unlock()
                        
                            4.销毁互斥锁        
                                int pthread_mutex_destroy()
                        
                    死锁:(在多个锁的使用时,在对加锁的推进顺序使用不当的造成)
                        因为对一些无法加锁的锁进行加锁,而导致程序卡死
                            
                    产生场景:
                            1.加锁/解锁的顺序不同
                        ** 2....
                        
                    **死锁产生的必要条件:
                        1.互斥条件(我操作的时候别人的能操作)
                        2.不可剥夺条件(我的锁,别人不能解)
                        3.请求与保持条件(拿着手里的,请求其他的,其他的不能请求到,手里的也不放)
                        4.环路等待条件(3)
 
                    如何预防死锁:破坏死锁产生的必要条件
                        
                    **避免死锁:
                        1.死锁检测算法
                        2.银行家算法                        
                
                如何实现同步:临界资源访问的合理性——生产出来才能使用——等待加唤醒
                    没有资源则等待(这是一种死等),生产资源后唤醒等待
                    
                    线程1如果操作条件满足,则操作,否则进行等待
                    线程2促进条件满足,唤醒等待的线程
                    
                    条件变量:
                        1.定义一个条件变量
                            pthread_cond_t    
                        2.初始化条件变量
                            int pthread_cond_init()
                        3.等待/唤醒
                            死等待:
                                int pthread_cond_wait()//先解锁在等待,使用原子操作保证安全
                                ——集合了解锁后挂起的操作(原子操作),有可能还又没来得及挂起就已经有人唤醒——则导致白唤醒,
                                因为含有临界资源,就必须加锁保护
                                
                                此操作共包含了3个操作:
                                    1.解锁        2.休眠        3.被唤醒后加锁
                                
                            限时等待,超时后则返回:
                                int pthread_cond_timedwait()
                            
                            
                            广播唤醒:(唤醒等待的人所有人)
                                int pthread_cond_broadcast()
                                
                            唤醒至少一个等待的人:
                                int pthread_cond_signal()
                                
                        4.销毁条件变量
                            int pthread_cond_destroy()
                    
                    条件变量为什么要搭配互斥锁使用:
                        因为条件变量本身只提供等待与唤醒的功能,因此具体什么时候的等待需要
                        用户来进行判断,这个条件的判断,通常涉及临界资源的操作(其他线程要通过修改文件,来促使条件满足)    
                        而这个临界资源二点操作应该受保护,因此搭配互斥锁使用。
                        
                    加锁:
                        条件判断-不满足
                            1.解锁
                            2.等待

以上是关于线程安全的主要内容,如果未能解决你的问题,请参考以下文章

如何创建线程?如何保证线程安全?

如何确保Java线程安全?

如何保证线程安全?

多线程(四):线程安全

如何创建线程?如何保证线程安全?

线程安全和非线程安全