Synchronized和Lock的区别
我们首先先大致的说一下他们的区别 然后举ReentrantLock实现精确唤醒的例子
- synchronized是关键字 属于JVM层面
Lock是具体类 (java.util.concurrent.Locks.Lock)
- synchronized 不用用户去手动释放锁 当synchronized代码执行完成之后会自动让线程释放锁的占用
ReentrantLock 则要用户去手动释放锁 若没有 则可能导致死锁现象
用lock()和unlock()方法
- synchronized 不可中断
ReentrantLock 可以中断
- synchronized 非公平锁
RenntrantLock 两者都可以 默认非公平锁 构造方法传入布尔值 true是公平锁 false是非公平锁
- 锁绑定多条件Condition
synchronized没有
ReentrantLock 用来实现分组唤醒需要被唤醒的线程们 可以精确唤醒 而不是像synchronized要么随即唤醒一个线程 要么全部唤醒
我们来看一个ReentrantLock实现精确唤醒的例子
题目 多线程之间按顺序调用 实现A->B->C三个线程启动
A打印5次 B打印10次 C打印15次
紧接着
A打印5次 B打印10次 C打印15次
这样的操作来10轮
注意 这道题核心是一定是A5次 B10次 C15次 这样算一轮 然后重复10轮
这样才能体现ReentrantLock实现
精确唤醒的意义
package com.zyk;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Data{
private int num=5;
private Lock lock=new ReentrantLock();
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
private Condition condition3=lock.newCondition();
public void print5() {
lock.lock();
try {
//判断
while (num!=5){
condition1.await();
}
//干活
for (int i = 0; i <5; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i );
}
//通知
num=10;
//通知打印10次的那个线程
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print10() {
lock.lock();
try {
//判断
while (num!=10){
condition2.await();
}
//干活
for (int i = 0; i <10; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i );
}
//通知
num=15;
//通知打印15的那个线程
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print15() {
lock.lock();
try {
//判断
while (num!=15){
condition3.await();
}
//干活
for (int i = 0; i <15 ; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i );
}
//通知
num=5;
//通知打印5次的那个线程
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class SyncAndReentrantLockDemo {
public static void main(String[] args) {
Data data=new Data();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.print5();
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.print10();
}
},"B").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.print15();
}
},"c").start();
}
}