Java支持多线程,每个线程分别执行自己的代码,所有线程共享堆内存。
在语言层面,对应的类是 Thread
, 启动方法为 Thread#start()
.
多线程编码时,如果未设置正确的同步,则可能会产生一些莫名其妙的BUG。
Java programming language memory model, 即Java编程语言内存模型, 另外,还有硬件层面的内存模型。
线程之间有多种通信方式, 其中最基础的叫做同步(synchronization), 通过管程(monitor)来实现.
每个Java对象都有一个相关联的管程,各个线程都可以锁定(lock)以及解锁(unlock)管程。 同一时刻,只能有单个线程持有管程的锁,试图锁定该管程的其他线程都会被阻塞(blocked)。
一个线程可以多次锁定同一个管程,解锁则是锁定的反操作。
可以对某个引用使用 synchronized
语句, 来获取具体对象上面的管程。 线程执行时,只有锁定了相应的管程才能继续运行,执行语句块中的代码。synchronized
语句块执行(正常执行/异常执行)完毕,会自动解锁一次该语句块对应的管程。
调用 synchronized
方法时会自动执行锁定操作,只要获取到对应的锁才会执行该方法的方法体。 实例方法锁定的是this
所指向对象的管程, 静态方法(static
) 锁定的则是对应 Class 对象的管程。 方法退出时,会自动触发一次相应管程的unlock操作。
Java语言不负责死锁的检测,由程序员负责处理。 必要时请使用高级别的锁定原语。
Java还支持其他的同步机制,例如 volatile
域以及 java.util.concurrent
包中的类。
每个对象都有一个关联的管程,也就有对应的等待集合(wait set),也就是线程集合。
新创建的对象,其等待集合是空的。增加或者减少等待集的过程是原子性的,对应的操作方法是 Object#wait
, Object#notify
, 和 Object#notifyAll
。 线程中断也会影响等待集, 但 sleep 和join并不会影响。