可重入锁、设计模式2(JAVA并发第四期)

p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解

目录

当一个线程需要获得多把锁的时候,便容易发生死锁
活锁出现在两个线程互相改变对方的结束条件,导致最后谁也无法结束
饥饿,即一个线程由于优先级太低,始终得不到CPU调度执行,也不能结束

ReentrantLock 可重入锁

相对于synchronized它具备如下特点

●可中断

●可以设置超时时间

●可以设置为公平锁(一般没必要,会降低并发度)

●支持多个条件变量

与synchronized一样,都支持可重入
可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁

如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住

java 复制代码
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    private  static ReentrantLock lock =new ReentrantLock();
    public static void main(String[] args) {
        lock.lock();
        try {
            System.out.println("main获得锁");
            m1();
        }finally {
            lock.unlock();
        }
    }

    public static void m1() {
        lock.lock();
        try {
            System.out.println("m1获得锁");
            m2();
        }finally {
            lock.unlock();
        }
    }

设计模式

固定顺序运行

java 复制代码
wait-notify形式
public class Main {
    //同步
    static final Object lock = new Object();

    static boolean t2runed = false;
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                while (!t2runed) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("t1");
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("t2");
                t2runed = true;
                lock.notify();
            }
        });

        t1.start();
        t2.start();
    }
}

-----------------------------------------------------------------------------

park-unpark形式
import java.util.concurrent.locks.LockSupport;

public class Main {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
           LockSupport.park();
            System.out.println("t1");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("t2");
            LockSupport.unpark(t1);
        });

        t1.start();
        t2.start();
    }
}

交替输出

java 复制代码
wait-notify形式

public class Main {
    public static void main(String[] args) {
        waitNotify wn = new waitNotify(1, 5);
        new Thread(()->{
            wn.print("a",1,2);
        }).start();
        new Thread(()->{
            wn.print("b",2,3);
        }).start();
        new Thread(()->{
            wn.print("c",3,1);
        }).start();

    }
}
/*
 * 输出内容  等待标记 下一个标记
 * a         1       2
 * b         2       3
 * c         3       1
 * */
class waitNotify{
    //等待标记
    private int flag;
    //循环次数
    private int loopNumber;

    public waitNotify(int flag, int loopNumber) {
        this.flag = flag;
        this.loopNumber = loopNumber;
    }

    //打印
    public void print(String str,int waitFlag,int nextFlag){
        for (int i = 0; i < loopNumber; i++) {
            synchronized (this){
                while(flag!=waitFlag){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.print(str);
                flag=nextFlag;
                this.notifyAll();
            }
        }
    }
}

await-singal形式
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) {
        AwaitSignal as = new AwaitSignal(5);
        Condition a = as.newCondition();
        Condition b = as.newCondition();
        Condition c = as.newCondition();
        new Thread(()->{
            as.print("a",a,b);
        }).start();
        new Thread(()->{
            as.print("b",b,c);
        }).start();
        new Thread(()->{
            as.print("c",c,a);
        }).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        as.lock();

        try{
            System.out.println("开始");
            a.signal();
        }finally {
            as.unlock();
        }
    }
}

class AwaitSignal extends ReentrantLock {
    private int loopNumber;
    public AwaitSignal(int loopNumber) {
        this.loopNumber = loopNumber;
    }

    public void print(String str, Condition current,Condition next) {
        for (int i = 0; i < loopNumber; i++) {
            lock();
            try {
                current.await();
                System.out.print(str);
                next.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                unlock();
            }
        }
    }
}


park-unpark形式
import java.util.concurrent.locks.LockSupport;

public class Main {

    static Thread t1;
    static Thread t2;
    static Thread t3;

    public static void main(String[] args) {
        ParkUnpark pu = new ParkUnpark(5);
        t1 = new Thread(()->{
            pu.print("a",t2);
        });
        t2 = new Thread(()->{
            pu.print("b",t3);
        });
        t3 = new Thread(()->{
            pu.print("c",t1);
        });

        t1.start();
        t2.start();
        t3.start();

        LockSupport.unpark(t1);
    }
}

class ParkUnpark{
    private int loopNumber;
    public  ParkUnpark(int loopNumber){
        this.loopNumber = loopNumber;
    }

    public void print(String str,Thread next){
        for(int i=0;i<loopNumber;i++){
            LockSupport.park();
            System.out.print(str);
            LockSupport.unpark(next);
        }
    }
}
相关推荐
zb200641204 分钟前
CVE-2024-38819:Spring 框架路径遍历 PoC 漏洞复现
java·后端·spring
2401_8955213414 分钟前
spring-ai 下载不了依赖spring-ai-openai-spring-boot-starter
java·人工智能·spring
何仙鸟41 分钟前
GarmageSet下载和处理
java·开发语言
wefly20171 小时前
免安装!m3u8live.cn在线 M3U8 播放器,小白也能快速上手
java·开发语言·python·json·php·m3u8·m3u8在线转换
yuweiade1 小时前
springboot和springframework版本依赖关系
java·spring boot·后端
ywf12151 小时前
springboot设置多环境配置文件
java·spring boot·后端
小马爱打代码1 小时前
SpringBoot + 消息生产链路追踪 + 耗时分析:从创建到发送,全链路性能可视化
java·spring boot·后端
jessecyj1 小时前
Spring boot整合quartz方法
java·前端·spring boot
苦瓜小生2 小时前
【前端】|【js手撕】经典高频面试题:手写实现function.call、apply、bind
java·前端·javascript
NGC_66112 小时前
Java 线程池:execute () 和 submit () 到底有什么区别?
java