java是如何开启线程的
1.继承thread类,重写run方法
2.实现runnable接口,重写run方法
3.实现callable接口。重写run方法,通过futuertask创建一个线程,获取到线程的返回值
4.通过线程池来开启线程
怎么保证线程的安全
普遍是加锁:
1.jvm提供的锁,也就是synchronized关键字
2.jdk提供的各种锁 lock
volatile和synchronized有什么区别
synchronized关键字用来加锁java线程信号量,volatile只是保持变量的线程可见性,通常适用于一个线程写,多个线程读的场景
volatile能不能保证线程安全
不能。volatile只能保证线程可见性,不能保证原子性
DCL(double check lock)单例为什么要加volatile
volatile防止指令重排,在DCL中,防止高并发情况下,指令重排造成线程安全的问题
java线程锁机制是怎么样的,偏向锁、轻量级锁、重量级锁有什么区别,锁机制是如何升级的
1.java的锁就是在对象的markword中记录一个锁状态。无锁,偏向锁、轻量级锁、重量级锁对应不同的锁状态
2.java的锁机制就是根据资源的激烈程度不断进行锁升级的过程
谈谈你对AQS的理解。AQS如何实现可重入锁
1.AQS是一个java线程同步的框架,是jdk中很多锁工具的核心实现框架
2.在AQS中,维护了一个信号量state和一个线程组成的双向链表队列。
java可重入锁-ReentrantLock实现细节
ReentrantLock支持两种获取锁的方式,一种是公平模型,一种是非公平模型。在继续之前,咱们先把故事元素转换为程序元素。
咱们先来说说公平锁模型:
初始化时, state=0,表示无人抢占了打水权。这时候,村民A来打水(A线程请求锁),占了打水权,把state+1,如下所示:
线程A取得了锁,把 state原子性+1,这时候state被改为1,A线程继续执行其他任务,然后来了村民B也想打水(线程B请求锁),线程B无法获取锁,生成节点进行排队,如下图所示:
初始化的时候,会生成一个空的头节点,然后才是B线程节点,这时候,如果线程A又请求锁,是否需要排队?答案当然是否定的,否则就直接死锁了。当A再次请求锁,就相当于是打水期间,同一家人也来打水了,是有特权的,这时候的状态如下图所示:
到了这里,相信大家应该明白了什么是可重入锁了吧。就是一个线程在获取了锁之后java是如何开启线程的1.继承thread类重写run方法java锻体十二,再次去获取了同一个锁,这时候仅仅是把状态值进行累加。如果线程A释放了一次锁,就成这样了:
仅仅是把状态值减了,只有线程A把此锁全部释放了,状态值减到0了,其他线程才有机会获取锁。当A把锁完全释放后,state恢复为0java线程信号量,然后会通知队列唤醒B线程节点,使B可以再次竞争锁。当然,如果B线程后面还有C线程,C线程继续休眠,除非B执行完了,通知了C线程。注意,当一个线程节点被唤醒然后取得了锁,对应节点会从队列中删除。