可重入锁、设计模式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);
        }
    }
}
相关推荐
青云计划10 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿10 小时前
Jsoniter(java版本)使用介绍
java·开发语言
探路者继续奋斗11 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd
消失的旧时光-194312 小时前
第十九课:为什么要引入消息队列?——异步系统设计思想
java·开发语言
A懿轩A12 小时前
【Java 基础编程】Java 面向对象入门:类与对象、构造器、this 关键字,小白也能写 OOP
java·开发语言
乐观勇敢坚强的老彭12 小时前
c++寒假营day03
java·开发语言·c++
biubiubiu070612 小时前
谷歌浏览器无法访问localhost:8080
java
大黄说说13 小时前
新手选语言不再纠结:Java、Python、Go、JavaScript 四大热门语言全景对比与学习路线建议
java·python·golang
烟沙九洲13 小时前
Java 中的 封装、继承、多态
java
识君啊13 小时前
SpringBoot 事务管理解析 - @Transactional 的正确用法与常见坑
java·数据库·spring boot·后端