Synchronized与lock锁区别

1、synchronized是java关键字,他是jvm层面; lock是接口(相应的实现比如ReentrantLock);

2、synchronized无法获取到锁的状态, lock可以获取到锁的状态;

3、synchronized是自动锁,如果代码执行完毕或发生异常, 他会自动释放锁的资源, lock手动锁,需要人工进行调用unlock方法进行释放锁的资源, 一般都是放在finally; 如果不释放会发生死锁;

4、synchronized如果线程a获取到锁的资源,发生阻塞,线程b会一直等待, 而lock如果获取不到锁的资源,线程不用等待就结束了;

5、synchronized是可重入、不可中断, 非公平;  Lock 可重入、 可判断、 可公平(两则皆可);

6、Synchronized是基于内存屏障实现锁; ReentrantLock是基于AQS实现锁;

7、Synchronized在JDK1.4引入的锁升级过程,由用户态切换到内核态;

8、synchronized唤醒线程和等待线程则使用的是Object提供的notify()、wait();方法, 而lock是condition里面提供的signal()、await()方法、 而lock可以获取多个condition可以实现线程循序执行(比如:下面代码1.0);

扩展:

synchronized实现是在jvm中使用monitorenter和monitorexit来实现同步且其中阻塞和唤醒是wait和notify,后者是juc包中的lock层次使用,依赖于AQS来实现加锁和解锁; 

LOCK一般是通过自旋和CAS的方式进行给程序加锁,当有一个线程抢到所的资源,其他则进行等待; 

Synchronized在1.6之前每次都要从内核申请额外的锁资源,这样的话都要设计到用户态和内核态的转换,比较浪费资源,而在大多数情况下只有一个线程操作资源,完全不需要重量级锁的。于是就引入了锁升级的过程。

偏向锁:当只有一个线程去抢一个资源,于是就会使用偏向锁,修改偏向锁的状态(记录锁的状态是在我们对象头里面的markwork记录锁的状态),说明这只有a线程来占有;

轻量级锁:于是又来了b、c线程他们就是把偏向锁的标识去除,然后升级到轻量级锁,他是通过cas+自旋的方式来抢锁的资源(这个抢锁的过程还是偏向与前一个申请偏向锁的a线程);

重量级锁:当a线程获取到锁,b、c线程他们一直在抢锁的资源,抢锁的过程他会消耗cpu的资源,如果十个线程过来,那么这些线程一直抢锁的资源,这样对cpu的资源消耗会比较大的,于是就引入了重量级锁,重量级锁是当我们线程自旋次数达到上限他会升级到重量级锁,向内核申请资源,直接让线程阻塞。这样的话会解决多个线程一个抢锁的资源;

1.0


    static final Lock lock = new ReentrantLock();
    static final Condition condition = lock.newCondition();
    static final Condition condition2 = lock.newCondition();
    static final Condition condition3 = lock.newCondition();
    private static int num = 0;

psvm {
    new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (num != 0) {
                        try {
                            condition.await();
                        } catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                    }
                    System.out.println("【" + Thread.currentThread().getName() + "】");
                    num = 1;
                    condition2.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "t1").start();

        new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (num != 1) {
                        try {
                            condition2.await();
                        } catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                    }

                    System.out.println("【" + Thread.currentThread().getName() + "】");
                    num = 2;
                    condition3.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "t2").start();

        new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (num != 2) {
                        try {
                            condition3.await();
                        } catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                    }
                    System.out.println("【" + Thread.currentThread().getName() + "】");
                    num = 0;
                    condition.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "t3").start();
    }
}

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
synchronizedlockJava中用于实现线程同步的两种不同机制。 1. synchronized关键字是Java语言提供的内置机制,用于保证代码块或方法在同一时刻只能由一个线程执行。synchronized关键字可以用于修饰代码块或方法,当一个线程进入synchronized代码块或方法时,会自动获取,并在执行完毕后释放synchronized关键字的是隐式的,由Java虚拟机自动管理。 2. Lock接口是Java.util.concurrent包提供的显式机制,也是一种更灵活、可控制性更强的机制。Lock接口的实现类可以通过调用lock()方法获取,并通过调用unlock()方法释放。与synchronized不同,Lock接口可以实现更细粒度的定,并提供了更多高级功能,如可重入、读写等。 下面是synchronizedLock之间的一些区别: - 可重入性:synchronized是可重入,即一个线程可以多次获取同一个;而Lock接口可以通过实现ReentrantLock类来实现可重入。 - 的获取方式:synchronized关键字是隐式的,在进入synchronized代码块或方法时自动获取,并在退出时释放;而Lock接口需要显式地调用lock()方法获取,并在finally块中调用unlock()方法释放。 - 等待可中断:通过Lock接口提供的lockInterruptibly()方法,可以在等待获取的过程中响应中断请求,而synchronized关键字在等待获取时无法响应中断。 - 公平性:Lock接口可以实现公平,即按照线程请求的顺序来获取,而synchronized关键字是非公平。 - 性能:在低竞争情况下,synchronized关键字的性能表现更好;而在高竞争情况下,Lock接口的性能更好。 总的来说,synchronized是一种简单易用的线程同步机制,适用于大部分场景;而Lock接口提供了更多灵活、可控制的定方式,适用于一些特殊需求的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值