秋招面试知识点----多线程篇

juc下有什莫

  • AQS:共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制。

    • 就是clh先进先出队列(节点有联系),
    • private volatile int state;//同步状态,使用volatile修饰保证线程可见性,还有就是同步状态cas操作
    • 模版模式,就是父类搞个模版,规划好方法执行顺序,就是一个方法里包含其他方法,子类只用修改其中一部分,运行时就会走子类地方法。
  • Automic原子类

  • countdownlanch,就是创建时给个容量,然后就是线程cutdown,然后最后wait,等待执行完

  • CyclicBarrier,就跟集齐七颗龙珠召唤神龙是的,一直wait,到数量一起执行

  • Semaphore,信号量,就这麽多资源有人acquire了,就要等着别人release

  • ReadWriteLock // 读写锁: 更加细粒度的控制 private ReadWriteLock readWriteLock = new ReentrantReadWriteLock() readWriteLock.writeLock().lock();

线程主要状态

①初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的成为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得cpu 时间片后变为运行中状态(running)。
阻塞(BLOCKED):线程阻塞于锁nodify,nodifyall。
等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)就是wait,join。
超时等待(TIME_WAITING):该状态不同于WAITING,它可以在指定的时间内自行返回wait(123)。

终止(TERMINATED):表示该线程已经执行完毕。

Java 线程状态变迁

sleep,wait区别

1、sleep是线程中的方法,但是wait是Object中的方法。

2、sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中。

3、sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。

4、sleep不需要被唤醒(休眠之后推出阻塞),但是wait需要(不指定时间需要被别人中断)。

进程和线程的区别

进程是操作系统资源调度的基本单位,程序在一个数据集上的一次动态执行,

线程是cpu任务调度

做个简单的比喻:进程=火车,线程=车厢

  • 线程在进程下行进(单纯的车厢无法运行)
  • 一个进程可以包含多个线程(一辆火车可以有多个车厢)
  • 不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
  • 同一进程下不同线程间数据共享(A车厢换到B车厢很容易)
  • **进程要比线程消耗更多的计算机资源线程上下文切换消耗少(**采用多列火车相比多个车厢更耗资源)
  • 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
  • 进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
  • 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-“互斥锁”
  • 进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量

Synchronized 和 Lock 区别

1、Synchronized 内置的Java关键字, Lock 是一个Java类

2、Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁 3、Synchronized 会自动释放锁,lock 必须要手动释放锁!如果不释放锁,死锁

4、Synchronized 线程 1(获得锁,阻塞)、线程2(等待,傻傻的等);Lock锁就不一定会等待下 去;

5、Synchronized 可重入锁,不可以中断的,非公平;Lock ,可重入锁,可以 判断锁,非公平(可以 自己设置);

6、Synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码!

死锁

使用 jps -l 定位进程号

jstack 进程号

Jmm

步骤一

线程1:先把initFlag变量从主内存中read读取出来,再load载入自己的工作内存,use使用线程1执行代码!initFlag。

步骤二

线程2:先把initFlag变量从主内存中read读取出来,再load载入自己的工作内存,use使用线程2执行代码initFlag=true,这时候值发生了改变,线程会再assign重新赋值到工作内存,然后store存储并写入主内存,write写入赋值到主内存中的变量。(线程2对缓存行lock加锁,write写入主内存后会解锁unlock,防止initFlag还未write写入主内存就被线程1读取为false)。

步骤三

线程1:因为initFlag被volatile修饰,使用MESI缓存一致性协议,线程1利用cpu总线嗅探机制监听到了initFlag值的修改,线程1中工作内存initFlag=false失效,这时候线程就拿不到工作内存的数据了,从而工作内存继续去读取主内存数据,变为true退出循环继续执行,体现了多线程同步运行共享变量副本的可见性。如果initFlag没有被volatile修饰,线程1将感知不到initFlag的变化,一直循环下去停止不了。

io多路复用

  • 同步阻塞IO(Blocking IO):即传统的IO模型。

  • 同步非阻塞IO(Non-blocking IO):由于socket是非阻塞的方式,因此用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,轮询消耗了大量的CPU的资源。

  • IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。

    • I/O多路复用(又称为“事件驱动”),操作系统为你提供了一个功能,当你的某个socket可读或者可写的时候,他可以给你一个通知。这样当配合非阻塞的socket使用时,只有当系统通知我哪个描述符可读了,我才去执行read操作,可以保证每次read都能读到有效数据而不做返回-1的无用功。select/poll/epoll/kqueue之类的系统调用函数来使用,这些函数都可以同时监视多个描述符的读写就绪状态,这样,多个描述符的I/O操作都能在一个线程内并发交替地顺序完成,这就是I/O多路复用

    select

    • select仅仅返回,但是并不会告诉你那个哪个socket上有数据,于是你得扫描一遍,才可以获取对应的socket
    • select只能监视1024个链接
    • select不是线程安全的

    poll

    • 去掉了1024个链接的限制

    epoll

    • epoll现在是线程安全的
    • epoll现在不仅告诉你socket组里面有数据,还会告诉你具体上哪个sock有数据,不用自己去扫描了
  • 异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。

同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值