控制线程间的执行顺序
CyclicBarrier类
- 让一组线程等待至某种状态后全部执行
关于CyclicBarrier可以参考这篇文章同步屏障CyclicBarrier
Thread.join()方法
控制线程间的同步执行,将交替执行的线程变成顺序执行的,在B线程前调用A线程的join函数,意为在A执行完后执行B线程
方法:
- t.join():调用线程t在此之前执行完成
- t.join(millseconds):等待t线程执行,等待时间为millseconds毫秒
CountDownLatch类
计数器的功能,例如在A线程执行前需要执行4个线程,可利用此计数器在4个线程执行完成后再执行A线程
java内存模型
从抽象的角度看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存,每个线程都有私有的本地内存,本地内存中存储了共享变量的副本
线程之间的通信方式
- 共享内存
- void notify() 唤醒在此对象监视器上等待的单个线程。
void notifyAll() 唤醒在此对象监视器上等待的所有线程。
void wait() 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法。
void wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
Volatile+缓存一致性解释
当一个变量被volatile修饰时:
- 当某个线程对该变量进行修改之后,就立即将修改后的值刷回主存,保证主存中永远都是最新的值
- volatile对该变量施加了缓存一致性协议,也就是说当前线程对该变量进行修改后,系统会通知其他线程它们工作缓存中的数据已经失效。当其他线程再次读取该变量时,就会从主存中读取该变量然后复制一份到自己的工作缓存中
- volatile保证了可见性但是不保证原子性
CAS操作
CAS有三个操作数,内存值V,旧的预期值A,要更改的新值B,当且仅当旧的预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做
CAS的问题:
- ABA问题:ABA问题是指在CAS操作的时候,其他线程将变量的值A改成了B之后又改回了A,本线程使用期望值A与当前变量进行比较的时候发现变量没有变,实际上该值已经被其他线程改变了。
解决方法:每次变量更新的时候,把变量的版本号加一,从而能够解决ABA问题 - 循环时间长开销大:自旋CAS如果长时间不成功,将给CPU带来非常大的开销
- 只能保证一个共享变量的原子操作