- 多线程概述
- 多线程描述的是一种情形:在主线程中有多个线程在运行。而通常情况下,我们在提及“多线程”的时候,指的是如下这种特定情况:
- 多个线程来自同一个Runnable实例。
- 多个线程使用同样的数据和代码。
- 互斥锁
在java语言中引入了,“对象互斥锁”的标记,这个标记用来保证在任何一时刻,只能有一个线程访问该对象。
关键字synchronized用来与对象互斥锁联系。当某个synchronized修饰时,表明该对象在任何一时刻只能由一个线程访问。
在Java中有两种使用synchronized的方式:
- 放在方法前面,这样,调用该方法的线程均将获得对象的锁。
- 放在代码块前面,用于修饰对象的引用。它也有两种形式:
- 用于修饰当前对象引用——synchronized(this){……}或synchronized{……}:代码块中的代码将获得当前对象引用的锁。
- 用于修饰当前对象引用——synchronized(otherObj){……}:代码块中的代码将获得指定对象引用的锁。
注意:synchronized锁定的不是方法或者代码块,而是对象。当synchronized被当作方法的修饰符时,它所取得对象锁将被转交给方法调用者。如果synchronized修饰的是对象引用,则取得的对象锁被转交给该引用指向的对象。
synchronized也可以用来修饰类,当将synchronized用在类前面时,表示这个类的所有方法都是synchronized的。
如果一个线程一直占用一个对象的锁,则其他的线程将永远无法访问该对象,
因此,需要在适当的时候,将对象锁归还。
- 当线程执行到synchronized块结束时,释放对象锁。
- 当在synchronized中遇到break、return或抛出Exception,则自动释放对象锁。
- 当一个线程调用wait()方法时,它放弃拥有的对象锁并进入等待队列。
- 死锁
所谓死锁是指,两个线程都互相等待对方释放lock。这种情形是不可预测或避开的。我们应该采取措施避免死锁的出现。
最常见的死锁形式:是当线程1持有对象A上的锁,而且正在等待B上的锁,而线程2持有对象B上的锁,却在等待对象A上的锁。这两个线程永远都不会获得第二个锁,或者释放第一个锁。他们只会永远等待下去。