JAVA多线程的同步 是通过对锁的控制实现的
虽然表面上 好像
类有一把锁(Class级) 保护 static 成员
类的实例(对象)有一把锁 保护非static成员
但是 JAVA 万物皆为对象的原则 其实原理都相同 类 不过是 JVM 的对象而已
线程的同步 就是对资源的竞争
有两种层次 第一种 我用了 你别用
第二种客气点 我要用了 但条件不满足时我会等
我用完会通知别人
对于第一种 用 synchronized 实现
一般在方法前
public synchronized void aa (){
doSomething()
}
相当于
public void aa () {
synchronized(this) { // 在此获得this锁
doSomething()
} // 在此释放this锁
}
因此可以 直接在代码中使用
public void aa () {
synchronized(obj) {
doSomething()
}
}
对于第二种 就要利用wait/notify 机制
A线程
synchronized(obj) {
while(条件不满足) {
obj.wait();
}
obj.doSomething();
}
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
线程B
synchronized(obj) {
设置条件
obj.notify();
}
当然 其中的obj 是 同一把锁 ,条件一般是两个线程同时使用的资源产生
在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
要注意的是
wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj)
调用obj.wait()后,线程A就释放了obj的锁,
否则线程B无法获得obj锁,
B在 synchronized(obj) {...} 执行完以后
才会真正释放了obj的锁,A才能真正得到obj的锁
最后有个外部强制线程非正常终止的问题
wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出
InterruptedException。
需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。
对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出
InterruptedException。但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出
InterruptedException。