java 知识点突击-(121-130)
Posted 栗子~~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 知识点突击-(121-130)相关的知识,希望对你有一定的参考价值。
文章目录
- 前言
- java 知识点扫盲目录
- java 知识点突击-(121-130)
- 创作不易、点关注、不迷路
- 点击主页、更精彩 !!!
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
java 知识点扫盲目录
https://blog.csdn.net/weixin_38316697/article/details/121991582
java 知识点突击-(121-130)
121 可重入锁-ReentrantLock原理?
概念:同一个线程能够获得同一把锁,不会造成死锁的出现。
根据CAS机制:比较并交换(原子性),保证当一个线程对共享资源的操作,其他线程无法访问,
基于AQS来实现(抽象队列同步器)
抢到了锁的线程,怎么处理? --不需要处理
没有抢到锁的线程,怎么处理?
– . 需要等待 (如果抢占锁失败,就会阻塞–>释放cpu的资源)
– . 需要排队(允许n个线程排队)
线程会不会处于一直活跃的状态?
答:不会,通过一个队列存储起来
如何让线程等待?
wait 、notify —(线程通信的机制、无法指定)
LockSupport(park,unpark)—(阻塞和唤醒指定的线程)
释放的过程,怎么处理?
LockSupport.unpark(线程) --》唤醒队列中的线程
122 说一下synchronized底层实现原理?
synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时还保证共享变量的内存可见性。
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
- 普通同步方法,锁是当前实例对象
- 静态同步方法,锁是当前类的class对象
- 同步方法块,锁是括号里边的对象
123 Synchronized和Volatile的区别是什么?
(1)volatile本质是在告诉JVM当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住;
(2)volatile仅能使用在变量级别,synchronized则可以使用在变量、方法和类级别;
(3)volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量修改的可见性和原子性;
(4)volatile不会造成线程的阻塞,synchronized可能会造成线程的阻塞;
(5)volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化;
124 Synchronized和Lock的区别是什么?
(1)首先synchronized是Java的内置关键字,在JVM层面,Lock是个Java类;
(2)synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁
(3)synchronized会自动释放锁(①线程执行完同步代码会释放锁;②线程执行过程中发生异常会释放锁),Lock需要在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
(4)用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2则等待。如果线程1阻塞,则线程2会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
(5)synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可);
(6)Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题;
125 Synchronized和ReentrantLock区别是什么?
synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多的灵活性,可以被继承,可以有方法,可以有各种各样的类变量,ReentrantLock比Synchronized的扩展性体现在以下几点上:
-
ReentrantLock可以对获得锁的等待时间进行设置,这样避免了死锁;
-
ReentrantLock可以获取各种锁的信息;
-
ReentrantLock可以灵活地实现多路通知;
另外,二者的锁机制其实也不一样:ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark work。
126 说一下Atomic的原理?
Atomic包中的类基本的特性就是在多线程环境下,当有多个线程同时对单个(包括基本类型及引用类型)变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。
Atomic系列的类中的核心方法都会调用unsafe类中的几个本地方法。首先要知道的一个东西就是Unsafe类,全名为sum.misc.Unsafe,这个类包含了大量的对C代码的操作,包括很多直接内存分配以及原子操作的调用,而它之所以标记为非安全的,是告诉你这个里面大量的方法调用都会存在安全隐患,需要小心使用,否则会导致严重的后果,例如在通过unsafe分配内存的时候,如果指定某些区域可能会导致一些类似C++一样的指针越界到其他进程的问题。
127 为什么需要 run ()和 start ()方法,我们可以只用 run ()方法来完成任务吗?
我们需要 run ()&start ()这两个方法是因为 JVM 创建一个单独的线程不同于普通方法的调用,所以这项工作由线程的 start 方法来完成,start 由本地方法实现,需要显示地被调用,使用这俩个方法的另外一个好处是任何一个对象都可以作为线程运行,只要实现了 Runnable 接口,这就避免因继承了 Thread 类而造成的 Java 的多继承问题。
128 在静态方法上使用同步时会发生什么事?
同步静态方法时会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。
扩展:
synchronized修饰static方法与非static方法的区别:
当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例), 作用范围是整个静态方法,作用的对象是这个类的所有对象。
当synchronized修饰一个非static方法时,多线程下,获取的是对象锁(即类的实例对象),
作用范围是整个方法,作用对象 是调用该方法的对象。
结论: 类锁和对象锁不同,它们之间不会产生互斥
129 在一个对象上两个线程可以调用两个不同的同步实例方法吗?
不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完该方法释放对象锁后才能执行其它同步方法。
130 锁优化的思路和方法?
130::01 减少锁持有时间
例子:
public synchronize void test()
test1();
methodIndex(); // 真正需要同步的代码
test2();
优化:
public void test()
test1();
synchronize(this)
methodIndex(); // 真正需要同步的代码
test2();
130::02 减少锁粒度
将大对象、拆成小对象,大大提高并发度,降低锁竞争
130::03 锁分离
ReadWriteLock:
传统锁下,读写共用一把锁,而ReadWriteLock将读锁和写锁相分离,在没有写的场景下,读读是不阻塞,无等待的,最高级别的并发,而在涉及写的时候,读和写都需要申请锁,因此写的过程中,可能会读到旧数据,导致数据不一致。
读和写的锁情况:
读锁 | 写锁 | |
---|---|---|
读锁 | 非阻塞 | 阻塞 |
写锁 | 阻塞 | 阻塞 |
ReadWriteLock在读多写少的情况下,可以提高性能。
130::04 锁粗化
通常情况下,为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽量短,即在使用完公共资源后,应该立即释放锁。只有这样,等待在这个锁上的其他线程才能尽早的获得资源执行任务。但是,凡事都有一个度,如果对同一个锁不停的进行请求、同步和释放,其本身也会消耗系统宝贵的资源,反而不利于性能的优化。
例子:
for(int i=0;i<list.size();i++)
synchronized(this)
...
优化:
synchronized(this)
for(int i=0;i<list.size();i++)
...
130::05 锁消除
在即时编译器时,如果发现不可能被共享的对象,则可以消除这些对象的锁操作
即如果在一段代码中,在堆上的所有数据【都不会逃逸出去被其他线程访问到】。那就可以把它当做私有栈上的数据来处理,同步加锁自然无需执行。
创作不易、点关注、不迷路
点击主页、更精彩 !!!
以上是关于java 知识点突击-(121-130)的主要内容,如果未能解决你的问题,请参考以下文章