一、sleep vs wait
1、共同点:wait() ,wait(long) 和 sleep(long) 的效果都是让当前线程暂时放弃 CPU 的使用权,进入阻塞状态
2、方法归属不同
①sleep(long) 是 Thread 的静态方法
②而 wait(),wait(long) 都是 Object 的成员方法,每个对象都有
3、醒来时机不同
①执行 sleep(long) 和 wait(long) 的线程都会在等待相应毫秒后醒来
②wait(long) 和 wait() 还可以被 notify 唤醒,wait() 如果不唤醒就一直等下去
③它们都可以被打断唤醒
4、锁特性不同
①wait 方法的调用必须先获取 wait 对象的锁,否则会报错,而 sleep 则无此限制
②wait 方法执行后会释放对象锁,允许其它线程获得该对象锁(我放弃,但你们还可以用)
③而 sleep 如果在 synchronized 代码块中执行,并不会释放对象锁(我放弃,你们也用不了)
二、lock vs synchronized
1、语法层面
•synchronized 是关键字,源码在 jvm 中,用 c++ 语言实现
•Lock 是接口,源码由 jdk 提供,用 java 语言实现
•使用 synchronized 时,退出同步代码块锁会自动释放,而使用 Lock 时,需要手动调用 unlock 方法释放锁
2、功能层面
•二者均属于悲观锁、都具备基本的互斥、同步、锁重入功能
•Lock 提供了许多 synchronized 不具备的功能,例如获取等待状态、公平锁、可打断、可超时、多条件变量
•Lock 有适合不同场景的实现,如 ReentrantLock, ReentrantReadWriteLock
3、性能层面
•在没有竞争时,synchronized 做了很多优化,如偏向锁、轻量级锁,性能不赖
•在竞争激烈时,Lock 的实现通常会提供更好的性能
三、lock公平、非公平演示
首先我们先看不公平的状态,这里创建了四个线程,线程t1是一开始的锁的持有者,t234只能进入阻塞队列,看看图2的代码功能是不断的创建线程,lock调用trylock,如果在时限内获取不了锁就返回一个结果,这样设计是为了不让不断创建的线程占用太多cpu。看图三的调试结果,不是等待最久的t2先获取了锁,而且另外一个线程
那我们将fair参数改成true,再看调试结果,就是所谓的公平状态。
四、lock条件变量
当我的持锁线程发现条件不满足,不能继续运行接下来的代码,这时候就可以让持锁线程暂时放弃锁,到condition这个队列等待,条件满足后将其唤醒,重新获得锁,从他上次终止的地方向下运行。
锁condition对象的await可让当前持锁线程进入队列,signal方法唤醒,signalAll方法可唤醒全部。