你可能不了解的Synchonized和ReentrantLock

面试中经常会问到的一类问题是多线程相关的, 比如如何处理Android中的多线程通信,如何处理并发问题。归根结底,处理Java的并发,都离不开锁。 我们将花三到四分钟了解两种锁的用法和不同, 还有什么是公平锁。

ReentrantLock 和 Synchronized 的比较

相同:ReentrantLock提供了synchronized类似的功能和内存语义。 不同: (1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现; (2)ReentrantLock功能性方面更全面,比如时间锁等候,可中断锁等候,锁投票等,因此更有扩展性。在多个条件变量和高度竞争锁的地方,用ReentrantLock更合适,ReentrantLock还提供了Condition,对线程的等待和唤醒等操作更加灵活,一个ReentrantLock可以有多个Condition实例,所以更有扩展性。 (3)ReentrantLock 的性能比synchronized会好点。 (4)ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁,而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以更容易产生死锁。

如何加锁
Synchronized

加锁有两种,方法同步(给方法增加synchronized声明)和代码块同步(给代码块增加synchronized声明)

ReentrantLock

获取锁的方式是通过 ReentrantLock 的对象 lock()来获取锁的, 必须记住一定要在finally方法中调用 unlock() 释放锁

关于锁的重入

锁是可以重复获取的,Synchronized和 ReentrantLock都是

public class SynchronizedTest {
    public void method1() {
        synchronized (SynchronizedTest.class) {
            System.out.println("方法1获得ReentrantTest的锁运行了");
            method2();
        }
    }
    public void method2() {
        synchronized (SynchronizedTest.class) {
            System.out.println("方法1里面调用的方法2重入锁,也正常运行了");
        }
    }
    public static void main(String[] args) {        
        new SynchronizedTest().method1();
    }
}
public class ReentrantLockTest {
    private Lock lock = new ReentrantLock();
    public void method1() {
        lock.lock();        
        try {
            System.out.println("方法1获得ReentrantLock锁运行了");
            method2();
        } finally {
            lock.unlock();
        }
    }
    public void method2() {
        lock.lock();        
        try {
            System.out.println("方法1里面调用的方法2重入ReentrantLock锁,也正常运行了");
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {        
        new ReentrantLockTest().method1();
    }
}
听说过公平锁吗?

Synchronized持有的锁是非公平的,因为CPU的调度算法是随机从等待队列里挑选一个线程, 可能会导致优先级低的线程永远得不到锁。 而ReentrantLock可以通过在构造方法中传入true来构造公平锁,保证线程按照时间的先后顺序执行。

public class LockFairTest implements Runnable{    //创建公平锁
    private static ReentrantLock lock=new ReentrantLock(true);
    public void run() {
        while(true){
            lock.lock();
            try{
                System.out.println(Thread.currentThread().getName()+"获得锁");
            }finally{
                lock.unlock();
            }
        }
    }
    public static void main(String[] args) {
        LockFairTest lft=new LockFairTest();
        Thread th1=new Thread(lft);
        Thread th2=new Thread(lft);
        th1.start();
        th2.start();
    }
}

结果如下

Thread-1获得锁
Thread-0获得锁
Thread-1获得锁
Thread-0获得锁
Thread-1获得锁
Thread-0获得锁
Thread-1获得锁
Thread-0获得锁
Thread-1获得锁
Thread-0获得锁
Thread-1获得锁
总结

区别: 1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

4)通过Lock可以知道有没有成功获取锁(tryLock()),而synchronized却无法办到。

5)Lock可以提高多个线程进行读操作的效率。

原文发布于微信公众号 - Android每日一讲(gh_f053f29083b9)

原文发表时间:2018-02-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JavaEdge

用弱引用堵住内存泄漏全局 Map 造成的内存泄漏找出内存泄漏HPROF 输出,显示 Map.Entry 对象的分配点弱引用WeakReference.get() 的一种可能实现用 WeakHashMa

36450
来自专栏我是攻城师

理解AbstractQueuedSynchronizer提供的独占锁和共享锁语义

Doug Lea前辈在JDK5中编写的AbstractQueuedSynchronizer抽象同步框架非常精辟,整个代码里没有使用像synchronized这样...

18820
来自专栏cmazxiaoma的架构师之路

JUC之CountDownLatch的源码和使用场景分析

最近工作不饱和,写写文章充充电。何以解忧,唯有Coding。后续更新的文章涉及的方向有:ThreadPoolExecutor、Spring、MyBatis、Re...

29210
来自专栏進无尽的文章

简述OC语言

对于一门语言的学习是需要时间领悟的,而对于一些原理性的问题,我们需要清楚其核心思想,知其然而知其所以然,这样才能有利于自己的后续发展。本文只是简述,没有面面具到...

23920
来自专栏java 成神之路

CountDownLatch 源码分析

34970
来自专栏Script Boy (CN-SIMO)

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1

场景:eclipse中编写java中用到数组 问题:       程序不报错但是运行过程中 终止,显示字样 “ Exception in thread "...

21300
来自专栏xdecode

JDK并发包总结

线程1, 线程2分别去获取lock1, lock2, 触发死锁. 最终通过DeadlockChecker来触发线程中断.

11820
来自专栏hotqin888的专栏

bootstrap treeview 增删改的正确姿势

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

51130
来自专栏Java面试通关手册

Java多线程学习(六)Lock锁的使用

我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailc...

92990
来自专栏微信公众号:Java团长

synchronized与Lock的区别与使用详解

昨天在学习别人分享的面试经验时,看到Lock的使用。想起自己在上次面试也遇到了synchronized与Lock的区别与使用。于是,我整理了两者的区别和使用情况...

16120

扫码关注云+社区

领取腾讯云代金券