多线程与高并发

多线程与高并发_第1张图片

1.线程创建的3种方式

2.线程的状态切换步骤

多线程与高并发_第2张图片

3.线程的5中状态

Java中的线程的生命周期大体可分为5种状态。

1. 新建(NEW):新创建了一个线程对象。

2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3. 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。

4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种: 

(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。

(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。

(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

5. 死亡(DEAD,称为Terminted更好):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

多线程与高并发_第3张图片

线程状态图

4.synchronized的底层实现

锁的种类(偏向锁,自旋锁,系统锁),锁的升级

偏向锁,记录这个线程的id,如果线程争用,升级为自旋锁,自旋10次后(默认10次)升级为重量级锁,向系统申请资源.

锁只能升级不能降级

执行时间短(加锁代码),线程数少,用自旋锁

执行时间长,线程数多,用系统锁

5.volatile

多线程与高并发_第4张图片

6.CAS(jdk1.8是Compare And Swap, jdk11.0是Compare And Set,无锁优化 自旋)

多线程与高并发_第5张图片

CPU源语支持,中间不能被打断

7.Unsafe

这是jdk1.8的

多线程与高并发_第6张图片

这是jdk11.0的

多线程与高并发_第7张图片

increment: sync,atomicXXX,LongAdder

8.CAS新类型锁——Reentrantlock

reentrantlock用于替代synchronized

由于m1锁定this,只有m1执行完毕的时候,m2才能执行

这里是复习synchronized最原始的语义

使用reentrantlock可以完成同样的功能

需要注意的是,必须要必须要必须要手动释放锁(重要的事说三遍)

使用syn锁定的话如果syn代码块执行完或者遇到异常,jvm会自动释放,但是lock必须手动释放锁

使用reentrantlock可以进行尝试锁定trylock,这样无法锁定,或者在指定时间内无法锁定就是放弃锁定

8.2公平锁和非公平锁

通过分析ReentrantLock中的公平锁和非公平锁的实现,其中tryAcquire是公平锁和非公平锁实现的区别,下面的两种类型的锁的tryAcquire的实现,从中我们可以看出在公平锁中,每一次的tryAcquire都会检查CLH队列中是否仍有前驱的 先是检查并设置锁的状态,这种方式会出现即使队列中有等待的线程,但是新的线程仍然会与排队线程中的对头线程竞争(但是排队的线程是先来先服务的),所以新的线程可能会抢占已经在排队的线程的锁,这样就无法保证先来先服务,但是已经等待的线程们是仍然保证先来先服务的,所以总结一下公平锁和非公平锁的区别:

1、公平锁能保证:老的线程排队使用锁,新线程仍然排队使用锁。 

2、非公平锁保证:老的线程排队使用锁;但是无法保证新线程抢占已经在排队的线程的锁。

8.3ReentrantLock和Synchronized的区别

cas和sync的区别

trylock可以尝试获取锁,获取不到就算了

lockinterruptibly 可以实现锁打断

ReentrantLock可以实现公平和非公平锁,Synchronized只有非公平的锁

9.CountDownLatch

10.CyclicBarrier可循环屏障

11.Phaser同步屏障

onAdvance是在栅栏推倒的时候自动调用

12.ReadWriteLock读写锁

读锁就是共享锁,写锁就是排他锁

zookeeper和redis(两种方法)实现分布式锁

13.Semaphore(起限流作用)

Semaphore直接翻译是信号灯的意思,字面理解是信号灯亮的时候才能执行,信号灯不亮的时候不能执行.

  Semaphore s = new Semaphore(2); //如果为1 则表示只允许一个线程同时执行,2则表示允许两个线程同时执行
  new Thread(()->{
    s.acquire(); //每当有一个线程执行acquire()方法后,就会减少1,当为0时,就不能执行了,所以最开始new对象的参数为多少就允许多少个线程同时执行
    s.release();
  })

14.Exchanger(用于线程之间交换数据用的,只能用于两个线程之间交换数据)

15.LockSupport

将当前线程阻塞,阻塞的方法LockSupport.park(),解除阻塞LockSupport.unpark()

多线程与高并发_第8张图片

16.多线程,高并发面试题

(1)实现一个容器,提供两个方法,add,size

写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束.

(2)写一个固定容量同步容器,拥有put和get方法,以及getCount方法,能够支持2个生产者线程以及10个消费者线程的阻塞调用.

17.源码阅读原则

多线程与高并发_第9张图片

你可能感兴趣的:(1024程序员节)