可重入锁、设计模式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);
        }
    }
}
相关推荐
后端AI实验室13 分钟前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai
程序员清风2 小时前
小红书二面:Spring Boot的单例模式是如何实现的?
java·后端·面试
belhomme2 小时前
(面试题)Redis实现 IP 维度滑动窗口限流实践
java·面试
Be_Better2 小时前
学会与虚拟机对话---ASM
java
开源之眼4 小时前
《github star 加星 Taimili.com 艾米莉 》为什么Java里面,Service 层不直接返回 Result 对象?
java·后端·github
Maori3165 小时前
放弃 SDKMAN!在 Garuda Linux + Fish 环境下的优雅 Java 管理指南
java
用户908324602736 小时前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
小王和八蛋6 小时前
DecimalFormat 与 BigDecimal
java·后端
beata6 小时前
Java基础-16:Java内置锁的四种状态及其转换机制详解-从无锁到重量级锁的进化与优化指南
java·后端
IT探险家6 小时前
你的第一个 Java 程序就翻车?HelloWorld 的 8 个隐藏陷阱
java