java中锁与监视器介绍
锁为实现监视器提供必要的支持。
锁是对象内存堆中头部的一部分数据。JVM中的每个对象都有一个锁(或互斥锁),任何程序都可以使用它来协调对对象的多线程访问。如果任何线程想要访问该对象的实例变量,那么线程必须拥有该对象的锁(在锁内存区域设置一些标志)。所有其他的线程试图访问该对象的变量必须等到拥有该对象的锁有的线程释放锁(改变标记)。
一旦线程拥有一个锁,它可以多次请求相同的锁,但是在其他线程能够使用这个对象之前必须释放相同数量的锁。如果一个线程请求一个对象的锁三次,如果别的线程想拥有该对象的锁,那么之前线程需要 “释放”三次锁。
1) 锁用来保护代码片段,任何时刻只能有一个线程执行被保护的代码。
2) 锁可以管理试图进入被保护代码的线程
3)
锁可以拥有一个或者多个相关的条件对象
4) 每个条件对象管理那些已经进入被保护的代码段,但还不能运行的线程
监视器是一中同步结构,它允许线程同时互斥(使用锁)和协作,即使用等待集(wait-set)使线程等待某些条件为真的能力。
他们是应用于同步问题的人工线程调度工具。讲其本质,首先就要明确monitor的概念,Java中的每个对象都有一个监视器,来监测并发代码的重入。在非多线程编码时该监视器不发挥作用,反之如果在synchronized 范围内,监视器发挥作用。
wait/notify/notifyAll必须存在于synchronized块中。并且,这三个关键字针对的是同一个监视器(某对象的监视器)。这意味着wait之后,其他线程可以进入同步块执行。
当某代码并不持有监视器的使用权时,去wait或notify,会抛出java.lang.IllegalMonitorStateException。也包括在synchronized块中去调用另一个对象的wait/notify,因为不同对象的监视器不同,同样会抛出此异常。
死锁:所有线程互相占用了对方的锁,导致所有线程挂起。
饥饿:某些线程因为某些原因(优先级过低)无法获得所需的资源,导致无法运行。
活锁:两个线程互相释放资源给对方,从而导致没有一个线程可以同时拿到所有资源正常执行。(出电梯时,和一个进电梯的人互相谦让,导致进电梯的人进不了,出电梯的人出不去)
- 点赞
- 收藏
- 关注作者
评论(0)