• 【面试题】synchronized和lock的区别/手写生产者消费者


    1. synchronized和lock的区别

    1. 原始架构
      synchronized是关键字,底层是通过monitor对象来实现的,其实wait()notify()等方法也依赖于monitor对象,因此wait()notify()等方法只能在同步代码中使用。
      主要是两个指令moniterentermoniterexit
      在这里插入图片描述
      lock则使用API的方式调用。
    2. 公平锁和非公平锁
      sychronized非公平锁。
      ReentrantLock默认也是非公平锁,但是可以通过构造方法实现公平锁 new ReentrantLock(true);//不传递默认是false,非公平锁
    3. 使用方法
      synchronized不需要用户手动释放锁,当synchronized代码执行完线程自动释放锁。
      lock 需要调用unlock()手动释放锁。(lock(),unlock()需要配合try/finally使用)
    lock.lock();
            try {
               // ...
            }finally {
                lock.unlock();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 等待是否可中断
      synchronized不可被中断,除非抛出异常或者方法正常执行结束。
      ReentrantLock可以中断trylock(long timeout,TimeUnit unit);也可以不中断lock();
    2. 绑定多个condition
      sychronized没有。(要么随机唤醒一个要么全部唤醒)
      ReentrantLock可以实现精准唤醒。
    3. Synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码!

    1.1 condition精准唤醒demo

    一共3个线程,线程A打印数字1,线程2打印数字1,2,线程3打印数据1,2,3,轮询10次。

    class Test {
        private int num = 1; // num:1线程A干活 num:2线程B干活 num:3线程C干活
        Lock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();
    
        void print1() {
            lock.lock();
            try {
                //1.判断
                while (num != 1) {
                    condition1.await();
                }
                //2.干活
                for (int i = 1; i <= 1; i++) {
                    System.out.println(Thread.currentThread().getName() + ",打印," + i);
                }
                //3.通知
                num = 2;
                condition2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        void print2() {
            lock.lock();
            try {
                //1.判断
                while (num != 2) {
                    condition2.await();
                }
                //2.干活
                for (int i = 1; i <= 2; i++) {
                    System.out.println(Thread.currentThread().getName() + ",打印," + i);
                }
                //3.通知
                num = 3;
                condition3.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        void print3() {
            lock.lock();
            try {
                //1.判断
                while (num != 3) {
                    condition3.await();
                }
                //2.干活
                for (int i = 1; i <= 3; i++) {
                    System.out.println(Thread.currentThread().getName() + ",打印," + i);
                }
                //3.通知
                num = 1;
                condition1.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    
    class Main {
        public static void main(String[] args) {
            Test test = new Test();
    
            new Thread(() -> {
                for (int i = 1; i <= 3; i++) {
                    test.print1();
                }
            }, "AA").start();
    
            new Thread(() -> {
                for (int i = 1; i <= 3; i++) {
                    test.print2();
                }
            }, "BB").start();
            new Thread(() -> {
                for (int i = 1; i <= 3; i++) {
                    test.print3();
                }
            }, "CC").start();
        }
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    在这里插入图片描述

    2. 手写生产者消费者2.0

    在这里插入图片描述

    class Test {
        private int num = 0;
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        void add() {
            lock.lock();
            try {
                while (num != 0) {
                    condition.await(); //等待
                }
                num++;
                System.out.println(Thread.currentThread().getName() + ",num" + num);
                condition.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
    
        }
    
        void sub() {
            lock.lock();
            try {
                while (num == 0) {
                    condition.await(); //等待
                }
                num--;
                System.out.println(Thread.currentThread().getName() + ",num" + num);
                condition.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
    
    class Main {
        public static void main(String[] args){
            Test test = new Test();
    
            new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    test.add();
                }
            }, "AA").start();
    
            new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    test.sub();
                }
            }, "BB").start();
        }
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    生产者消费者2.0这个文章更详细:https://blog.csdn.net/wd_888/article/details/105154184?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-105154184-blog-48290937.pc_relevant_multi_platform_whitelistv6&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-105154184-blog-48290937.pc_relevant_multi_platform_whitelistv6&utm_relevant_index=5

    3. 手写生产者消费者3.0–todo

  • 相关阅读:
    Spring Thymeleaf模版注入分析
    马斯克拟打造xAI“算力超级工厂”,助力聊天机器人Grok
    wireshark初步认识
    Spring Boot + Vue的网上商城之商品信息展示
    代码随想录第43天|416. 分割等和子集,1049. 最后一块石头的重量 II, ​494.目标和,​ 474.一和零(一窍不通)
    Python 异步编程原理篇之新旧协程实现对比
    网页构造与源代码
    前端研习录(28)——JavaScript Element对象及其属性讲解及示例分析
    2022年全球市场弦乐器的弦总体规模、主要生产商、主要地区、产品和应用细分研究报告
    Franka机械臂使用记录
  • 原文地址:https://blog.csdn.net/yzx3105/article/details/126655948