Java同步器简述
一、概述
在并发编程领域,有两大核心问题:一个是互斥,即同一时刻只允许一个线程访问共享资源;另一个是同步,即线程之间如何通信、协作。主要原因是,对于多线程实现实现并发,一直以来,多线程都存在2个问题:
- 线程之间内存共享,需要通过加锁进行控制,但是加锁会导致性能下降,同时复杂的加锁机制也会增加编程编码难度
 - 过多线程造成线程之间的上下文切换,导致效率低下
 
因此,在并发编程领域中,一直有一个很重要的设计原则:“不要通过内存共享来实现通信,而应该通过通信来实现内存共享。”
简单来说,就是尽可能通过消息通信,而不是内存共享来实现进程或者线程之间的同步。
- 并发(
Concurrent):在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。 - 并行(
Parallel):当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行。 - 信号量(
Semaphore):是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用,也是作系统用来解决并发中的互斥和同步问题的一种方法。 - 信号量机制(
Semaphores):用来解决同步/互斥的问题的,它是1965年,荷兰学者Dijkstra提出了一种卓有成效的实现进程互斥与同步的方法。 - 管程(
Monitor):一般是指管理共享变量以及对共享变量的操作过程,让它们支持并发的一种机制。 - 互斥(
Mutual Exclusion):一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。即就是同一时刻只允许一个线程访问共享资源的问题。 - 同步(
Synchronization):两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。即就是线程之间如何通信、协作的问题。 - 对象池(
Object Pool):指的是一次性创建出N个对象,之后所有的线程重复利用这N个对象,当然对象在被释放前,也是不允许其他线程使用的,一般指保存实例对象的容器。 
二、线程同步机制
2.1 多线程同步器
| 同步器 | 简述 | 
|---|---|
| volatile | 轻量级的同步机制 | 
| synchronized | 同步锁 | 
2.2 线程阻塞工具类
| 同步器 | 简述 | 
|---|---|
| LockSupport | AQS中控制线程的实现类,是Java并发基础组件中的基础组件。 | 
2.3 线程锁
| 同步器 | 简述 | 
|---|---|
| AQS | 同步器基类 | 
| ReentrantLock | 锁 | 
| Condition | 条件锁 | 
| ReentrantReadWriteLock | 读写锁 | 
| StampedLock | 邮戳锁 | 
三、线程辅助类
| 辅助类 | 简述 | 
|---|---|
| Semaphore | 信号量 | 
| CountDownLatch | 减计数器 | 
| CyclicBarrier | 加法计数器 | 
| Exchanger | 交换器 | 
| Phaser | 阶段 | 
四、总结
Java三种等待唤醒机制:
synchronized搭配Object的wait、notifyReentrantLock的await和signal方法LockSupport的park和unpark
Object类和ReentrantLock.newCondition提供的阻塞唤醒机制十分相似,体现在:
- 要求阻塞和唤醒是有序的:它们都只能先阻塞再唤醒。否则会抛
IllegalMonitorStateException异常,且被阻塞的线程不能被唤醒。 - 依赖加锁或同步代码块:调用
Object的等待唤醒方法时要搭配synchronized一起用。即Object的wait和notify要写在sync同步代码块内;调用ReentrantLock.newCondition的await和signal方法时要搭配lock,unlock一起用。否则也会抛IllegalMonitorStateException异常,且被阻塞的线程不能被唤醒。 
LockSupport类与前两者不同:
LockSupport类支持先唤醒后阻塞,不会抛异常(底层是通过permit通行证实现的)。LockSupport类不依赖加锁代码块,直接LockSupport.park,LockSupport.park调用即可,较方便。

                
            
        
浙公网安备 33010602011771号