原始构成
synchronized是关键字,属于JVM层面
javap -c 的结果显示
synchronized是可重入锁
11:是正常退出 17:是异常退出【保证不产生死锁和底层故障】
Lock是java.util.concurrent.locks包中的一个接口 是API层面的锁
使用方法
synchronized不需要手动释放锁,当synchronized代码执行完后系统自动让线程释放对锁的占用
ReentrantLock则需要用户手动释放没有主动释放的锁,可能出现死锁现象。需要lock、unlock和try/catch一起使用
等待是否可中断
synchronizated不可中断,除非抛出异常或者正常运行完成
reentrantLock可中高端
- 设置超时方法tryLock 【new ReentrantLock().tryLock(1,TimeUnit.SECONDS);】
- lockInterruptibly()放代码块中,调用interrupt()方法中断【new ReentrantLock().lockInterruptibly();】
是否是公平锁
synchronizated是非公平锁
reentrantLock源码:默认是非公平锁。也可以传参true为公平锁 false为非公平锁
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
} /**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
锁是否绑定多个条件Condition
synchronizated没有,只能随机唤醒一个(notify()),或者唤醒全部唤醒(notifyAll())
ReentrantLock用来实现分组唤醒需要唤醒的线程,可以精确唤醒某个线程。
例如:多线程之间按顺序调用 实现线程之间按顺序启动【精确唤醒的举例】
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* 一个拍照的景点 有3个人要按顺序排单人照
* 张三想要拍1张 李四想要拍3张 王五想要拍5张
* 他们按照这个顺序排了两个景点
*/
class Plat{
private int id = 1; // 3人的编号
private Lock lock = new ReentrantLock();
private Condition person1 = lock.newCondition();
private Condition person2 = lock.newCondition();
private Condition person3 = lock.newCondition();
public void person1TakePhoto(){
lock.lock();
try{
while (id != 1){
person1.await();
}
for (int i = 0; i < 1; i++) {
System.out.println(Thread.currentThread().getName()+ "拍了"+(i+1)+"张照片");
}
id = 2;
person2.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void person2TakePhoto(){
lock.lock();
try{
while (id != 2){
person2.await();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()+ "拍了"+(i+1)+"张照片");
}
id = 3;
person3.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void person3TakePhoto(){
lock.lock();
try{
while (id != 3){
person3.await();
}
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+ "拍了"+(i+1)+"张照片");
}
id = 1;
person1.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
} }
public class ReentantLockTest {
public static void main(String[] args) throws InterruptedException {
Plat plat = new Plat();
new Thread(()->{
for (int i = 0; i < 2; i++) {
plat.person1TakePhoto();
}
},"张三").start();
new Thread(()->{
for (int i = 0; i < 2; i++) {
plat.person2TakePhoto();
}
},"李四").start();
new Thread(()->{
for (int i = 0; i < 2; i++) {
plat.person3TakePhoto();
}
},"王五").start();
}
}
输出结果:
张三拍了1张照片
李四拍了1张照片
李四拍了2张照片
李四拍了3张照片
王五拍了1张照片
王五拍了2张照片
王五拍了3张照片
王五拍了4张照片
王五拍了5张照片
张三拍了1张照片
李四拍了1张照片
李四拍了2张照片
李四拍了3张照片
王五拍了1张照片
王五拍了2张照片
王五拍了3张照片
王五拍了4张照片
王五拍了5张照片