在Java 5以前,可以用synchronized关键字来实现锁的功能,它可以用在代码块和方法上,表示在执行整个代码块或方法之前线程必须取得合适的锁。
不管是同步代码块还是同步方法,每次只有一个线程可以进入,其他线程JVM会将它们挂起(放入到等锁池中)。这种结构在并发理论中称为临界区(critical section)。
Java 5的并发编程
- 更好的线程安全的容器
- 线程池和相关的工具类
- 可选的非阻塞解决方案
- 显示的锁和信号量机制
原子类
java.util.concurrent包下面有一个atomic子包,利用了现代处理器的特性,可以用非阻塞的方式完成原子操作。显示锁
基于synchronized关键字的锁机制有以下问题:
- 锁只有一种类型,而且对所有同步操作都是一样的作用
- 锁只能在代码块或方法开始的地方获得,在结束的地方释放
- 线程要么得到锁,要么阻塞,没有其他的可能性
Java 5对锁机制进行了重构,
显示的锁都实现了java.util.concurrent.Lock接口,主要有两个实现类:
- ReentrantLock - 比synchronized稍微灵活一些的重入锁
- ReentrantReadWriteLock - 在读操作很多写操作很少时性能更好的一种重入锁
CountDownLatch
CountDownLatch是一种简单的同步模式,它让一个线程可以等待一个或多个线程完成它们的工作从而避免对临界资源并发访问所引发的各种问题。
主要方法
public CountDownLatch(int count);
public void countDown(); // 当前线程调用此方法,则计数减一
public void await() throws InterruptedException; // 调用此方法会一直阻塞当前线程,直到计时器的值为0
ConcurrentHashMap
ConcurrentHashMap是HashMap在并发环境下的版本。
CopyOnWriteArrayList
CopyOnWriteArrayList是ArrayList在并发环境下的替代品。
BlockingQueue
可以用BlockingQueue来实现生产者-消费者并发模型,当然在Java 5以前也可以通过wait和notify来实现线程调度。
Callable接口
Future接口
FutureTask接口
Java 7的并发编程
TransferQueue,它比BlockingQueue多了一个叫transfer的方法,如果接收线程处于等待状态,该操作可以马上将任务交给它,否则就会阻塞直至取走该任务的线程出现。