Java多线程基础

目录

同步方式

常用对象

一、volatile变量

二、ThreadLocal

三、Future

四、ExecutorCompletionService

五、Thread

并发容器

一、ConcurrentHashMap

二、CopyOnWriteArrayList

线程池

一、ExecutorService

疑问

基础

一、概念

二、注意点

三、其它


java线程是通过映射到操作系统的原生线程上来实现的,所以线程调度最终还是取决于操作系统,所以阻塞唤醒线程都需要从用户态转换到内核态,可能转换的开销比代码执行的开销还大,所以是重量级的。

 

同步方式

1、将所有可变状态封装在对象内部,并通过对象内置锁对所有访问可变状态的代码路径进行同步。

2、监视器模式:把对象所有可变状态封装起来,并由对象自己的内置锁来保护。

3、委托:如:Collections.synchronizedList(new ArrayList<>());

 

常用对象

一、volatile变量

1、不会将变量上的操作与其它内存操作一起重排序,不会被缓存在寄存器或其它处理器不可见的地方,因此读取volatile类型变量时总放回最新写入的值。

2、只能保证可见性,通常用作简单的状态标识。

 

二、ThreadLocal

1、使线程中的某个值与保存值的对象关联起来,使用某个变量的线程都存有一份独立的副本。

2、线程值保存在Thread对象中。

 

三、Future

1、表示任务的生命周期

2、get方法任务时阻塞的

TimeoutException:超时
InterruptedException:任务被中断
ExecutionException:任务抛出异常会被封装成ExecutionException抛出

3、cancel方法

true:会中断线程停止任务。

false:如果任务还没执行会中断任务,如果任务已经开始执行会让任务执行下去。

 

四、ExecutorCompletionService

1、作用:提交了一组计算任务,得到其中完成了的任务。

 

五、Thread

1、interrupt:中断线程(并不意味着立即停止目标线程正在进行的工作,只是传递了请求中断的消息)

2、isInterrupted:目标线程中断状态

3、静态的interrupted:清除当前线程的中断状态(清除中断状态的唯一办法),并返回它之前的值。

4、sleep()等阻塞方法,发现中断时会提前返回,并会清除中断状态,抛出InterruptedException。

5、join():线程执行join方法后,只有改线程任务执行完后,才会执行接下来的代码。

6、UncaughtExceptionHandler通过这个来捕获运行时异常,只能是execute提交的任务,submit提交的任务不行。

 

六、条件队列

1、内置锁:

wait:会自动释放锁、并挂起当前线程

notify:会从等待的多个线程中选址一个来唤醒

2、显式锁(Condition):await,signal

范例:

synchronized (lock){
while(isfull()){
lock.wait();
}
//dosomething
}

 

并发容器

一、ConcurrentHashMap

1、分段锁

2、size和isEmpty被弱化,如:size方法返回的是一个估计值。

二、CopyOnWriteArrayList

1、每次修改时,都会创建并重新发布一个新的容器副本。

 

线程池

一、ExecutorService

1、shutdown:不再接受新任务,等待已经提交的任务执行完成(包括还未开始执行的任务)

2、shutdownNow:取消所有运行中的任务(不再启动队列中还没开始执行的任务),返回所有已提交但尚未开始的任务。

3、invokeAll:提交一组任务,若超时,还没有完成的任务会被取消;

 

疑问

1、线程栈的地址空间

2、DelayQueue

3、句柄

4、套接字

5、newtaskfor

6、关闭钩子的使用 Runtime.getRuntime().addShutdownHook()

7、通信量

 

基础

一、概念

1、发布:是对象能在当前作用域以外的代码中使用,如其它对象中使用该对象的引用。可能破坏安全性。

2、逸出:不该发布的对象发布了。

3、线程封闭:仅在单线程内访问数据,不需要同步。局部变量和ThreadLocal,但需要确保封闭在线程中的对象不会从线程中逸出。

4、ad-hoc线程

5、对象不可变

  • 对象创建后状态不能修改
  • 对象所有域都是final类型
  • 对象正确创建(this引用没有逸出)

6、安全发布

  • 静态初始化函数中初始化对象引用
  • 对象引用保存在volatile类型域或AtomicReferance对象中
  • 对象引用保存在正确构造对象的final域中
  • 对象引用保存在由锁保护的域中(如:Vector)

 

二、注意点

1、执行时间较长的计算,不要持有锁。(如:网络IO)

2、非volatile类型的long和double变量,JVM允许将64位的读或写操作分解为两个32位的操作。

3、不要在this引用中使构造函数逸出。

4、每个线程都会维护两个执行栈,一个用于Java代码一个用于原生代码,JVM默认情况会生成一个复合栈,约0.5MB;

5、大量独立且同构的任务并发处理时,多线程才能使性能真正的提升。明确任务边界;分析粒度更细的并行性;

6、Socket IO或等待内置锁而阻塞,中断线程只能设置线程的中断状态,别无它用。

7、自旋等待(CPU时钟周期浪费)、休眠(低相应性)、Thread.yield(让出一定时间使另一个线程运行)、条件队列(如:wait)

三、其它

1、安全性

2、原子性:原子变量提供了与volatile相同的内存语义,此外还支持原子的更新操作。

3、内存可见性

4、posix线程

5、每个对象都有一个内置锁

6、重排序:编译器操作顺序重排序,并将数值缓存在寄存器中;CPU处理器特定的缓存中。

7、不希望ExecutorService被暴露出去但不希望其被修改时,可用Executors.unconfigurableExecutorService()将其封装起来

8、notify:需要持有条件队列对象相关联的锁,JVM会从这个条件队列上等待的多个线程中选择一个来唤醒。

 

死锁

原因:两个线程以不同的顺序来获得相同的锁,如果按照相同的顺序来请求锁就不会有死锁的风险。

1、获得锁的同时调用外部方法要小心

2、资源死锁:A线程拿着d1连接要d2连接,B线程拿着d2连接要d1连接。

线程饥饿死锁:有界线程池与相互依赖的任务不能一起使用。饥饿指线程无法访问它所需的资源而不能继续执行时。

3、支持定时的锁

4、活锁:线程不断重复执行相同的操作,而该任务总会失败,加入随机性可防止活锁。

 

性能分析

1、上下文切换:线程所需数据不在cpu缓存中,挂起和恢复的性能开销

2、内存同步(内存栅栏:缓存时效,不能重排序),锁粒度粗化,自旋锁,锁消除。同步会增加共享内存总线上的通信量。

3、缩小锁竞争(快进快出)

4、减少竞争的锁(分段锁)

5、Amdahl定律:减少被串行执行的部分

6、原子变量降低更新热点域的开销,细粒度原子操作,并使用处理器底层并发原语(cas)

 

显示锁

一、ReentrantLock

可中断

可定时

可轮询

可公平

非块结构锁

对于公平锁,可轮训的trylock仍然会插队

二、读写锁ReentrantReadWriteLock

1、允许多个读操作同时进行,但是只允许一个写操作

2、可重入

3、默认是非公平的锁

4、线程持有写锁不能在不释放写锁的情况下获得读锁,反之可以。

5、如果锁由读线程持有,另一个线程请求写锁,那么其他读线程都不能获得读取锁,直到写线程释放写入锁。

三、为什么优先使用内置锁

1、他俩性能一致

2、内置锁有锁消除、锁粗化等优化措施

3、内置锁操作可以与特定栈帧关联起来,排查问题可以有更多信息。

四、Condition

Lock.newCondition

Lock和Condition相当于内置锁和条件队列的关系 ,每个Lock可以有任意数量的Condition。

继承了lock的公平性,对于公平锁,线程会依照FIFO顺序从Condition.await中释放,调用await和signal方法时也必须持有锁对象。

要使用更高级特性,如:使用公平特性、每个锁上对应多个等待线程集时。

五、AQS

用于构建锁和同步器的框架

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值