这篇文章介绍了并发编程中的几个概念。其实很多概念在笔者之前的文章中已经介绍过了。例如:并发与并行、同步与异步、锁与信号量等。参考《并发编程专栏》,本文介绍了一些比较深入的利息计算概念。一、临界区为了方便大家理解,我们先来看下图。我们可以把房子看成一个进程,把每个房子里的住户和它的活动看成一个线程,饮水机、健身器材、厕所都是共享资源。这里的共享资源其实就是临界区的概念。临界区内的资源一次只能被一个线程(常驻)使用,所以一旦临界资源被占用,其他线程(常驻)只能等待。例如,在出租屋中,A住户占用厕所,在他使用厕所的这段时间里,厕所的资源是他独享的。如果此时B居民也想上厕所,则只能等A居民上完厕所后继续使用该资源。2.阻塞与非阻塞了解了临界区的概念之后,阻塞的概念就很容易理解了。一个线程先占用了临界区的资源,此时其他线程要使用临界区的资源,就必须等待。这种占用临界区资源,阻塞其他线程继续执行的情况就是线程阻塞(Blocking)。但是说到非阻塞,一般是指是否阻塞当前线程本身,比如:我执行一个任务,比如用饮水机接水。我拿了一个杯子去接水,我只好在饮水机前等着水喝完。这是一个阻塞线程。如果我拿杯子接水,把杯子放在饮水机下面,杯子装满水后,饮水机会自动给我发送一个异步通知(比如声音报警)。我可以在这期间做其他事情,这是一个非阻塞线程(Non-Blocking)。从编程的角度来看,非阻塞线程一般是通过回调函数或者响应式编程来实现的。3、死锁、饥饿和活锁死锁:我们看上图,路口A车道的A1车转向B车道,但是B车道的入口被B1车占了;路口B车道的B1车转入C车道,但C车道入口被C1车占用;路口C车道C1车转入D车道,但D车道入口被D1车占用;D车道的D1车在路口转入A车道,但A车道的入口被A1车占据;也就是说,由于资源竞争,线程之间互相需要对方的资源却无法释放,导致线程无法获得下一步所需要的资源,从而造成死锁。饥饿:比如一个农夫喂鸡,如果有五只鸡,他们每次都会给五只鸡准确的饲料量。难免有些鸡吃的比计划的多,最终某只鸡吃不饱饲料。由于得不到足够的饲料,它比较瘦弱,抓食能力差。恶性循环,最后很有可能饿死。具体到编程层面,某个线程A的优先级比较低,然后优先级高的线程往往会占用资源不释放。线程A长时间无法有效执行,处于饥饿状态。在极端情况下,可能会发生饥饿。活锁:相对于死锁和饥饿,活锁是一种相对较好的状态。生活中想必每个人都遇到过这样的情况。你在楼梯拐角处遇到一个同事,空间有限,所以两人住在一起。你向左移动,你的同事向左移动;你向右移动,你的同事向右移动;所以你们都不能前进,这是典型的活锁。因为人类是高智慧动物,懂得礼让,活锁的问题对人类来说很容易解决。只要其中一个不动,另一个就会过去。但是多线程在面对活锁的时候就没那么聪明了。可能会出现不断释放资源(向左移动)和占用资源(向右移动)的循环。即使最终解锁活锁,其资源开销和时间成本也是巨大的。欢迎关注我的博客,本文转载更多优质知识合集,注明出处(一定要有链接,不能只是文字):字母哥博客-zimug.com如果觉得对你有帮助,请点赞分享!您的支持是我创作不竭的动力!.另外,作者近期输出了以下优质内容,期待大家的关注。《kafka修炼之道》《手摸手教你学Spring Boot2.0》《Spring Security-JWT-OAuth2一本通》《实战前后端分离RBAC权限管理系统》《实战SpringCloud微服务从青铜到王者》
