文章目录
前言
对synchronized与reentrantLock区别的学习,予以记录!
一、synchronized与ReentrantLock五大区别
一张表总结本文内容:
项目 | synchronized | ReentrantlLock |
---|---|---|
原始结构 | jvm层面关键字 | API层面java.util.concurrent.locks.Lock |
使用方法 | 不需要用户手动释放锁,底层为monitorenter与monitorexit(1:2,正常退出与异常退出) | 需要用户手动释放锁,lock()与unlock()在try finally语句块来完成 |
等待是否可中断 | 不可中断,除非抛出异常或者正常运行完成 | 可中断①设置超时方法tryLock(Long timeout,TimeUnit unit);②代码块中使用lock.lockInterruptibly(),调用Thread.currentThread().interrupt();中断 |
加锁是否公平 | 非公平锁 | 默认为非公平锁,构造参数可传入Boolean参数值,true为公平锁,false为非公平锁 |
有无绑定多个条件的condition | 没有,要么随机唤醒一个线程notify(),要么唤醒全部线程notifyall() | 有,可以精确唤醒需要唤醒的线程condition.await(),condition.signal()/condition.signalAll() |
- 原始结构
- 使用方法
- 等待是否可以被中断
- 加锁是否是公平的
- 有无绑定条件的多个condition
二、代码验证condition
1、Demo01:使用ReentrantLock按顺序循环打印数字
AAA打印5次,BBB打印10次,CCC打印15次,紧接着,AAA打印5次,BBB打印10次,CCC打印15次 打印10轮
/*1.线程操作资源类
* 2.判断 干活 通知
* 3.防止多线程状态下的虚假唤醒
*
* 多线程按顺序调用
AAA打印5次,BBB打印10次,CCC打印15次
紧接着
AAA打印5次,BBB打印10次,CCC打印15次
打印10轮
* */
class ShareResource{
public int num=1;//A:1 B:2 C:3
private Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
Condition condition1=lock.newCondition();
Condition condition2=lock.newCondition();
public void print5(){
lock.lock();
try {
//判断
while (num!=1){
condition.await();
}
//干活
for (int i = 0; i < num * 5; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//通知
this.num=2;
condition1.signalAll();
} catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public void print10() {
lock.lock();
try {
//判断
while (num!=2){
condition1.await();
}
//干活
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//通知
this.num=3;
condition2.signalAll();
} catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public void print15(){
lock.lock();
try {
//判断
while (num!=3){
condition2.await();
}
//干活
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//通知
this.num=1;
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
}
public class SyncReentrantLockDemo {
public static void main(String[] args) {
ShareResource resource = new ShareResource();
new Thread(()->{
for (int i = 0; i < 10; i++) {
resource.print5();
}
},"AAA").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
resource.print10();
}
},"BBB").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
resource.print15();
}
},"CCC").start();
}
}
2、Demo02:使用ReentrantLock打印奇偶数
public class PrintJOS {
private int start=0;
private ReentrantLock lock=new ReentrantLock();
Condition condition1=lock.newCondition();
Condition condition2=lock.newCondition();
public void printJ(int end){
lock.lock();
try {
//判断,如果是偶数,使当前线程await
while (start%2==0) {condition2.await();}
//干活,不是偶数,开始打印基数
while(start<=end) {
System.out.println(Thread.currentThread().getName() + " " + start);
//通知,让start++
start++;
condition1.signalAll();
condition2.await();
}
condition1.signalAll();
} catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public void printO(int end){
lock.lock();
try {
while (start%2!=0) { condition1.await();}
while(start<=end) {
System.out.println(Thread.currentThread().getName() + " " + start);
start++;
condition2.signalAll();
condition1.await();
}
condition2.signalAll();
} catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
PrintJOS printJOS = new PrintJOS();
new Thread(()->{
printJOS.printO(100);
},"aaa").start();
new Thread(()->{
printJOS.printJ(100);
},"bbb").start();
}
3、Demo03:使用synchronized打印奇偶数
class Main {
private int count = 0;
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
new Thread(()->{
try {
main.printEven(16);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try {
main.printOdd(16);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"B").start();
}
//打印奇数方法
public synchronized void printOdd(int end) throws InterruptedException {
while (count % 2 == 0) {//如果是偶数,则阻塞,释放锁
this.wait();
}
while (count<=end){
System.out.println(Thread.currentThread().getName() + count++);
notifyAll();
this.wait();
}
notifyAll();
//唤醒阻塞线程
}
//打印偶数方法
public synchronized void printEven(int end) throws InterruptedException {
while (count % 2 != 0) {//如果是奇数,则阻塞,释放锁
this.wait();
}
while (count<=end){
System.out.println(Thread.currentThread().getName() + count++);
notifyAll();//唤醒阻塞线程
this.wait();
}
notifyAll();
}
}