跟我学代码架构设计模式之--锁和线程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w1857518575/article/details/85245975

上篇讲到锁可以用来解决多线程同时访问同一资源时的同步问题,即锁可以控制多线程对函数关联资源的的同步访问。这一篇我来简单分析下锁如何解决同步问题的。

在讲锁之前,我们我们先来讨论下wait和notify方法,这两个方法是用来控制线程执行的。说白了就是控制线程状态的流转,wait控制线程本身挂起等待到某个对象的阻塞队列中,线程由就绪或执行态转换成等待状态;notify方法是用来通知某个挂起阻塞队列中的线程,让其中的某个线程可以恢复执行,此时线程由等待状态变为执行状态。

wait、和notify方法为啥和锁关系这么密切呢?显而易见的原因是,线程在执行函数的时候,在一个资源得不到的时候,或者说得不到锁的时候,只有两种选择,要不就是死循环在那,要不就是挂起等待,等着资源或者说锁被其他线程释放后通知本线程继续执行!  wait和notify除了用在线程同步问题的解决中,在没有同步问题的多线程编程中,wait和notify还可以用来实现普通的等待和通知机制,即单纯的改变线程执行状态机来解决某些问题----比如:IO编程中的阻塞和非阻塞!

好了,下面来说说锁!

锁就相当于对多线程共享资源的看门人,其实可以理解为一个原子的状态变量,可以简单到只有两个操作——lock和unlock!lock就是原子的修改锁变量状态为上锁态,unlock就是原子的修改锁状态为未上锁态!

没有上锁态被某个线程修改为上锁态后就可以访问资源,其他的线程再去获取锁状态的时候发现锁被上锁,只有两种选择:死循环等待或者阻塞等待被执行,其中死循环等待的锁俗称自旋锁,阻塞等待的锁是普通的阻塞锁~ 自旋锁是乐观锁(这里不讲)

把锁上锁的线程在访问完资源后必须要释放锁,即修改锁状态为未上锁状态,以便让其他线程有机会出来竞争锁~这里分两种情况:自旋锁直接修改锁状态为未上锁就可以,对于阻塞锁解锁的线程还要notify通知其他线程恢复执行来竞争锁~

再来说一说死锁:

所谓死锁就是一个线程想要获取未上锁状态的锁,但是永远获取不到! 其实就是这么简单的概念!至于为什么获取不到锁,是因为代码的错误导致占有锁的线程永远不会释放锁!

再来说一说可重入锁:

所谓可冲重入锁就是在同一个已经获取锁的线程内,再多次调用获取锁会不会产生死锁,会产生死锁的锁就是不可重入锁,不会死锁的就是可重入的锁。普通的不可重入锁,当在一个线程内获取了锁后,锁的状态就变为了上锁态,然后当前线程内再次调用获取锁,发现锁是上锁态,自己就挂起阻塞等待或者自旋等待了,这样导致的后果是占用锁的当前线程永远不会释放锁,其他线程和自己都无法继续执行!这样就导致了死锁!

如何实现可重入呢?很简单,只需要一个线程在获取锁的时候判断下锁是不是已经被当前线程获取了,如果是,就忽略锁的锁状态,直接默认获取锁,如果锁不是被当前线程获取的,才阻塞等待或者自旋锁等待!

(完)

猜你喜欢

转载自blog.csdn.net/w1857518575/article/details/85245975