线程安全
对共享数据(shared)和可变状态(mutable)的访问,共享是针对同时访问而言,可变是生命周期角度而言。
解决线程安全的常用方法
1、java.util.concurrnet串行机制
使用原子变量类: AtomicLong/Intetger/Boolean等 其优于volatile
CopyOnWriteArrayList 代替 List;
并发容器:
CouncurrentHashMap : 分段锁(Lock Striping),并发访问下实现更高吞吐量;
HashTable 、synchronizedMap
阻塞队列:
BlockingQueue
工具类: 信号量(Semaphore)、栅栏(Barrier)、
闭锁(Latch):确保某些线程等其他线程弯成后再执行
2、内置锁
java体统内置锁机制,如synchronized,其有可重入性,即某个线程试图获得自己的锁时,则会成功。
常用加锁做法是,将所有可变状态封装在对象内部。
3、volatile
变量不会被缓存在寄存器或其他cup不可见的地方,其不是加锁,所以不会阻塞,因此轻量级(不发生上下文切换和调度)。
3、LocalThread
提供set、get接口,仅在线程内部访问
原理:为每个使用该变量的线程都创建一个副本
4、final
语义:当构造函数结束时,final类型的值保证其他线程访问该对象时,值可见。
属于安全发布的一种方式(即一个线程在创建该对象时,其他线程可引用到该对象最新值),通俗讲,若成员变量时final类型,一旦对象对其他线程可见,则final成员也必须赋值了。
eg:如果存在并发问题,需要同步机制访问或使用concurrentHashmap,而final修饰不可变对象,可并发访问,而不用使用同步机制。
5、显示锁:Lock
volatile
synchronized 内置锁
ReentrantLock 显示锁(性能更优):主要提供可轮询、定时、可中断操作
6、创建、中断线程
Callable(接口):带返回结果,从线程的生命周期角度考虑(End-of-Lifecycle),提供任务执行状态和取消(cancel)、中断(interrupt)功能。
Runnable/Thread:只能前进,不能后退的线程。
7、Executor框架
提供线程的抽象,基于生产者–消费者模式
线程池是线程的所有者,若要停止一个线程,应该使用线程池技术
如 FutureTask(可取消的任务)、Executor框架(工作线程已存在,不用等待创建线程提高响应性);
8、CAS
以上均为基于锁和阻塞的原子考虑。而CAS(compare-and-swap)比较并交换,是针对当下流行的多处理器而设计,是乐观技术,即多个线程尝试使用CAS同时更新时,只有一个能更新成功,且不会挂起。
主要包括 3 个操作数:1)需读写的内存位置V ;2)进行比较的值A;3)拟写入的新值B,
含义:我认为V的值应该是A,若是,V 更新成B;若否,返回V的值
使用与竞争性不高时。
8、性能考虑
资源密集型:cpu密集型、数据库密集型分析
10万+





