Java 多线程(二):多线程并发

0x0001 synchronized 同步方法

为了避免多个线程同时访问 同一个对象 的实例变量时,可能发生的“非线程安全”问题,可以用 synchronized 修饰方法进行避免。在方法前添加 synchronize 关键字,使得多个线程在执行该方法时,以排队的方法排队处理。当一个线程想要执行同步方法中的代码时,线程首先尝试去获得方法上的锁,若能够拿到这把锁,该线程就可以执行该同步方法;否则,该线程就会不断的尝试去拿这把锁,直到拿到为止,而且有可能是多个线程同时去争抢这把锁。

synchronized 可以在任意对象的方法上加锁,而加锁的这段代码被称为“互斥区” 或 “临界区”。

0x0002 synchronized 同步方法中的锁属于谁?

同步方法中关键字 synchronized 取得的锁都是 对象锁,哪一个线程先执行带有 synchronized 关键字的方法,哪一个线程就持有该方法 所属对象 的锁,那么其他对线程只能呈等待状态,前提是 多个线程访问的是同一个对象

如果多个线程访问不同对象,那么 JVM 会创建多个锁。如果多个线程访问多个对象,那么执行结果显示为异步的。通过 Github Code 中的 one()、two() 的对比可得到此结论,结论:多个对象多个锁

因为同步方法的锁为对象锁,所以当多个线程访问同一个对象中的多个同步方法时,同样呈现同步效果,但是若是访问 其他非同步方法 时,则呈现异步效果。一般的,需要对操作共享资源的方法进行同步操作。

锁的主体是对象,而不是线程,只是因为线程持有了对象的锁,才有了多线程的同步性。

0x0003 synchronized 锁重入

关键字 synchronize 用于 锁重入 的功能,也就是当一个线程得到一个对象锁之后,再次请求此对象锁时是可以再次得到该对象的锁的。具体表现:synchronize 方法/块的内部调用 本类 的其他 synchronize 方法/块时,是永远可以获得锁的。可重入锁 支持在父子继承关系

0x0004 出现异常,锁自动释放

当一个线程执行代码时出现异常,其所持有的锁会自动释放。

0x0005 同步不支持继承性

子类继承父类中的同步方法,则子类中的该方法不具有可同步性。


知识链接:

Java多线程编程核心技术