• 【第八章 死锁、lock锁、synchronized和lock的异同、线程通信、sleep()和wait()的异同】


    第八章 死锁、lock锁、synchronized和lock的异同、线程通信、sleep()和wait()的异同

    1.死锁
    ①不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
    ②出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。
    ③我们使用同步时,要避免出现死锁。
    2.解决线程安全问题的方式三:lock锁

    public class LockTest {
        public static void main(String[] args) {
            Window2 w1=new Window2();
            Thread t1=new Thread(w1);
            Thread t2=new Thread(w1);
            Thread t3=new Thread(w1);
            t1.start();
            t2.start();
            t3.start();
        }
    }
    class Window2 implements Runnable{
        private int ticket=100;
        //1.实例化ReentrantLock
        private ReentrantLock lock=new ReentrantLock();
        @Override
        public void run() {
            while (true){
                try{
                    //调用锁定方法,lock()
                    lock.lock();
                    if(ticket>0){
                        System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket);
                        ticket--;
                    }else {
                        break;
                    }
                }finally {
                    //调用解锁方法,unlock()
                    lock.unlock();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    3.synchronized和lock的异同
    ①相同点:二者都可解决线程安全问题。
    ②不同点:
    synchronized是隐式锁:在执行完相应的同步代码以后,自动的释放同步监视器,有代码块锁和方法锁。
    lock是显式锁:需要手动的启动同步lock(),同时结束同步,也需要手动的实现unlock(),只有代码块锁。使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。
    4.线程通信
    ①涉及线程通信的方法:
    wait():一旦执行此方法,当前线程进入阻塞状态,并释放同步监视器。
    notify():一旦执行此方法,就会唤醒wait的一个线程,如果有多个线程被wait,就唤醒优先级高的。
    notifyAll():一旦执行此方法,就会执行所有被wait的线程。
    ②说明:
    wait()、notify()、notifyAll()三个方法必须使用在同步代码块或同步方法中。
    wait()、notify()、notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器。
    wait()、notify()、notifyAll()定义在java.lang.Object类中

    public class CommunicationTest {
        public static void main(String[] args) {
            Number number=new Number();
            Thread t1=new Thread(number);
            Thread t2=new Thread(number);
            t1.setName("线程1");
            t2.setName("线程2");
            t1.start();
            t2.start();
        }
    }
    class Number implements Runnable{
        private int number=1;
        @Override
        public void run() {
            while (true){
            synchronized (this) {
                notify();
                if (number <= 100) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    try {
    //使得调用如下wait()方法的线程进入阻塞状态,wait会释放锁。
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    5.sleep()和wait()的异同
    相同点:一旦执行方法,都可以使当前的方法进入阻塞状态.
    不同点
    ①两个方法声明的位置不同,Thread中声明sleep(),Object类中声明wait()。
    ②调用的要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用在同步代码块或同步方法中。
    ③关于是否释放同步监视器:如果两个方法都使用在同步方法或同步代码块中,sleep()不会释放锁,wait()会释放锁。

  • 相关阅读:
    日本卫生设备行业协会:日本温水喷淋马桶座出货量达1亿套
    Echart 知识图谱--连接线段
    Echarts 配置项 series 中的 data 是多维度
    java swing 布局心得(避免忘记)
    Redis学习笔记18:基于spring data redis及lua脚本的分布式锁
    第十一章 枚举和注解
    spark任务,使用 repartition 对数据进行了重新分区,但任务输入数据大小仍存在不均衡
    Vue组合式 api 的常用知识点
    使用Bochs调试操作系统代码
    【Perl】与【Excel】
  • 原文地址:https://blog.csdn.net/qq_43742813/article/details/126860552