![](https://img-blog.csdnimg.cn/20201014180756754.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程和锁
ThunderWay
北京工业大学计算机研究生就读
展开
-
sleep()和wait()的区别和共同点
区别:1. sleep方法没有释放锁,但是wait释放了锁2. wait()被调用后不会自动苏醒,需要别的线程调用同一对象的notify()/notifyAll()方法;而sleep()执行后会自动苏醒。3. wait()通常用于线程之间的通信,而sleep()一般是用于暂停。共同点:两者都可以暂停线程的执行...原创 2020-10-17 12:29:55 · 412 阅读 · 0 评论 -
什么是线程死锁?如何避免死锁?
线程死锁:多个线程同时被阻塞,他们中的一个或者全部在等待某个资源被释放,由于线程被无限期的阻塞,因此程序不可能正常终止。产生死锁必须具备的四个条件:1.互斥条件:该资源任意时刻只由一个线程占用。2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完之后才释放资源。4. 循环等待条件:若干个进程之间形成一种头尾相接的循环等待资源关系。如何避免线程死锁(破坏其中一个条件即可):1.原创 2020-10-17 12:25:50 · 477 阅读 · 0 评论 -
介绍一下乐观锁和悲观锁?
1. 悲观锁就是每次拿数据都认为会修改数据,所以每次只要一个线程可以访问共享数据,其他线程等待,如synchronized和ReentrantLock。场景用于多写的场景,因为冲突比较多。2. 乐观锁就是每次拿数据都认为不会修改数据,所以不上锁,但是每次更新的时候都判断一下数据有没有更改,常用的是版本号更新和CAS算法。用于多读的场景,因为冲突比较少,增加系统吞吐量。3. CAS,比较和交换,无锁算法。只有当需要修改的值域期待值一样的时候,才更新,否则会执行一个自旋操作,不断重试。乐观锁的缺点:原创 2020-07-29 21:21:35 · 300 阅读 · 0 评论 -
线程池实现有哪些?FixedThreadPool底层用的是什么任务队列?
阿里巴巴强制不让使用Executors创建,使用ThreadPoolExecutor创建。Executors返回线程池对象弊端如下:FixedThreadPool和SingleThreadExecutor:允许请求队列最大长度为Integer.MAX_VALUE,导致OOM;CachedThreadPool和ScheduledThreadPool:允许创建线程的最大数量为Integer.MAX_VALUE,导致OOM。并发库中有个类是BlockingQueue,就是阻塞队列,这个类提供了两个方法,.原创 2020-07-28 21:42:26 · 386 阅读 · 0 评论 -
介绍一下ReentrantLock
ReentrantLock是java.util.concurrent.locks中的一个可重入锁类,在高竞争的条件下有更好的性能,可以中断。ReentrantLock是基于AQS实现的,AQS是基于FIFO队列实现的,AQS的子类只需要重写模板模式方法即可。ReentrantLock可以通过构造方法实现公平锁,但一般是非公平锁。非公平锁的实现是线程1调用lock()方法,将state更新为1,然后设置当前线程为独占模式,如果线程2想要获取锁会调用acquire方法,如果tryAcquire返回失败,将线原创 2020-07-27 21:59:40 · 135 阅读 · 0 评论 -
介绍一下AbstractQueuedSynchronizer(AQS)?
AQS是一个基于FIFO队列,用于构建阻塞锁或者同步器的框架。AQS原理就是:如果请求的共享资源空闲,那么将请求资源的线程设置为有效线程,将共享资源设置为锁定的状态;如果请求的资源正在被占用,那么就需要一套线程阻塞等待唤醒时刻锁分配的机制,这个机制AQS是基于CLH队列锁实现的,将暂时获取不到资源的线程加入到队列中。CLH队列是一个虚拟的双向队列,只存在节点之间的关联关系,AQS将每个请求共享资源的线程封装到CLH所队列的节点中来实现锁的分配。AQS使用一个int类型的变量表示同步状态,用volatil原创 2020-07-27 21:26:48 · 126 阅读 · 0 评论 -
使用ReentrantLock的场景
1. 使用可重入锁时。2. 并发竞争很大的时候。3. 需要使用可中断锁。4. 尝试等待执行:发现该操作已经在执行了,等待一段时间,超时了就不等。原创 2020-07-27 11:26:11 · 376 阅读 · 0 评论 -
ExecutorService中execute()和submit()的区别
execute()传递Runnable的实例作为参数,提交线程,没有返回值,而submit()用于提交需要返回值的任务,有返回值,Future作为返回值对象,表示一个线程的生命周期,可以判断任务是否执行成功。...原创 2020-07-27 10:33:36 · 269 阅读 · 0 评论 -
实现Callable和Runnable的区别
1. Callable定义的方法是call(),Runnable中定义的是run()。2. Callable中的call()可以有返回值,Runnable中的run()没有返回值。3. Callable中的call()可以抛出异常,Runnable中的run()不能抛出异常。...原创 2020-07-27 10:30:06 · 279 阅读 · 0 评论 -
synchronized和volatile的区别
volatile关键字的本质是告诉jvm,该变量在寄存器中的值是不确定的,需要在主存中读取,而synchronized关键字是锁住当前变量,只有当前线程可以访问,其他线程等待。1. volatile只能作用于变量,而synchronized可以作用于变量、方法和代码块2. 多线程访问volatile不会发生阻塞,而synchronized关键字可能发生阻塞。3. volatile能够保证数据的可见性,就是在多个线程之间是可见的,不能保证原子性,而synchronized关键字都可以保证。4.原创 2020-07-26 17:02:58 · 314 阅读 · 0 评论 -
介绍一下Condition
Condition是代替了对象监视器,将对象监视器的方法分解开,以便这些对象与锁进行不同的组合使用。Lock是替代了synchronized方法和语句块,而Condition是替代了对象监视器方法的使用,一个Condition实例需要和一个锁进行绑定。...原创 2020-07-25 22:01:36 · 117 阅读 · 0 评论 -
启动线程时,start()和run()的区别
1. run()只是类中的一个普通的方法,调用它还是从主线程中执行,没有启动多线程,程序依然要顺序执行,执行完run()才能继续往下执行。2. start()启动多线程,才是一个真正的多线程启动,不需要等待run方法,可以继续执行下面的方法。调用Thread类的start()方法,这时线程处于就绪状态,只要有cpu片段,线程就会运行run()方法,run()结束,线程终止。...原创 2020-07-25 21:54:51 · 176 阅读 · 0 评论 -
为什么会出现锁机制
java允许多线程并发,多线程情况下共享同一个资源变量的时候,会导致数据的不一致,所以锁机制可以保证数据的准确和唯一。原创 2020-07-25 20:13:55 · 166 阅读 · 0 评论 -
为什么要用线程池?
1. 降低资源消耗。降低了重复创建和销毁线程的资源消耗。2. 提高响应速度,任务到达的时候,线程不需要等就可以执行。3.提高线程的管理。原创 2020-07-25 17:59:25 · 64 阅读 · 0 评论 -
synchronized关键字的底层原理以及JDK1.6之后的底层优化
synchronized关键字底层原理属于JVM层面。1. synchronized关键字修饰同步代码块,synchronized同步代码块的实现使用的是monitorenter和monitorexit指令,monitorenter指令作用于同步代码块开始的地方,monitorexit作用于同步代码块结束的地方。当执行monitorenter指令的时候,线程试图获取当前锁对象,也就是获取monitor的持有权,只有当锁计数器为0的时候,才可以获取到,锁计数器自增,变为1,当执行到monitorexit指原创 2020-07-24 16:48:18 · 570 阅读 · 0 评论 -
synchronized关键字的使用
synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证它修饰的方法或代码块在任意时刻只有一个线程执行。主要有三种用法。1. 修饰同步代码块,线程进入代码块时需要获取指定锁对象。2. 修饰实例方法,线程进入实例方法时需要获取当前对象实例作为锁对象。3. 修饰静态方法,线程进入静态方法时需要获取类对象作为锁对象。...原创 2020-07-24 16:37:43 · 83 阅读 · 0 评论 -
synchronized和ReentrantLock的区别?
1. 这两个都是可重入锁。可重入锁就是自己可以获取自己的内部锁。比如当一个线程获取了某个对象的锁,这个锁还没有释放,该线程想要继续获取该对象的锁,还是可以获取的,这就是可重入锁。同一个线程每获取一次对象锁,内部的锁计数器就加一,只有当锁计数器下降到0的时候,锁才释放。2. synchronized依赖于JVM,而ReentrantLock依赖于API。synchronized的优化都是依赖jvm,我们看不到,而ReentrantLock依赖API,通过lock(),unlock()和try/finall原创 2020-07-24 12:15:19 · 132 阅读 · 0 评论