• synchronized和lock有什么区别?


    一、原始构成

    synchronized是关键字属于JVM层面,monitorenter(底层是通过monitor对象来完成,其实wait/notify等方法也依赖monitor对象只有在同步代码块和同步方法中才能调用wait/notify等方法)

    Lock是具体的类,是api层面的锁;

    二、使用方法

    synchronized不需要用户手动释放锁,synchronized代码执行完成以后系统会自动让线程释放对锁的占有

    ReentrantLock则需要用户手动去释放锁,若没有主动释放锁,就有可能导致死锁现象。需要使用lock()和unlock()方法配合try finally语句块来完成。

    三、等待是否可以中断

    synchronized不可中断,除非抛出异常或者正常运行完成。

    ReetrantLock可中断,

      1. 设置超时方法tryLock(long timeout, TimeUnit unit);

      2.lockInterruptibly()放入代码块中,调用interrupt()方法可中断;

    四、加锁是否公平

    synchronized是非公平锁

    ReentrantLock默认是非公平锁,可设置为公平锁。

    五、锁绑定多个条件condition

    synchronized没有; 

    ReentrantLock用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,而不是像synchronized要么随机唤醒一个,要么唤醒全部线程。

    六、案例

    题目:多线程之间按找顺序调用,实现A->B->C三个线程启动,要求如下:

    AA打印5次,BB打印10次,CC打印15次,重复上述过程10次.

    class ShareResource{
        private int number = 1; // A:1, B:2, C:3
        private Lock lock = new ReentrantLock();
        private Condition conditionA = lock.newCondition();
        private Condition conditionB = lock.newCondition();
        private Condition conditionC = lock.newCondition();
        public void print5(){
            try {
                lock.lock();
                while (number != 1){
                    conditionA.await();
                }
    
                for (int i = 1; i <= 5; i++){
                    System.out.print("A");
                }
                System.out.println();
                number++;
                conditionB.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        public void print10(){
            try {
                lock.lock();
                while (number != 2){
                    conditionB.await();
                }
    
                for (int i = 1; i <= 10; i++){
                    System.out.print("B");
                }
                System.out.println();
                number++;
                conditionC.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void print15(){
            try {
                lock.lock();
                while (number != 3){
                    conditionC.await();
                }
    
                for (int i = 1; i <= 15; i++){
                    System.out.print("C");
                }
                System.out.println();
                number = 1;
                conditionA.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    public class SynchronizedLockDifference {
    
        public static void main(String[] args) {
            ShareResource shareResource = new ShareResource();
            new Thread(()->{
                for (int i = 1; i <= 10; i++){
                    shareResource.print5();
                }
            }, "A").start();
    
            new Thread(()->{
                for (int i = 1; i <= 10; i++){
                    shareResource.print10();
                }
            }, "B").start();
    
            new Thread(()->{
                for (int i = 1; i <= 10; i++){
                    shareResource.print15();
                }
            }, "C").start();
    
        }
    }

    输出结果:

    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    AAAAA
    BBBBBBBBBB
    CCCCCCCCCCCCCCC
    
    Process finished with exit code 0
  • 相关阅读:
    redis 日常使用
    centos7新装mysql 5.7
    spring 的常用功能
    软件安装教程
    每日成长17年1月
    ubuntu下不用拔盘就可以重新识别usb设备
    使用Linux遇到的一些问题和解决方案
    在XEN上启动guest时loopback设备不足
    使用virtualenv搭建python虚拟开发环境
    Linux局域网登陆响应时间过长
  • 原文地址:https://www.cnblogs.com/ch-forever/p/10788674.html
Copyright © 2020-2023  润新知