因为多线程,所以我们需要对线程进行一些调度,也就是对线程进行一些处理,防止多线程带来的不同步问题。
在Java中,大的说有两种机制去实现多线程的同步,但是本质上来讲,是一种机制,那就是锁。
首先,是Java中的 java.util.concurrent.locks 中的锁。
这个包中有一个接口 Lock, 有一个类 ReentrantLock 实现了 Lock。
该方法中有一个lock方法,也就是获取锁,一旦某一个线程执行到这个方法,该线程就获得了锁。
如果别的线程如果执行到该方法,而锁已经被另一个线程获取了,则该线程被阻塞,直到获得锁的线程执行到 unlock 方法。
也就是说,如果获得锁的线程没有知道 unlock 方法,则别的线程永远不能运行 lock 和 unlock 之间的代码。
为了保证unlock方法用于被执行,一般都采用如下的格式开发:
Lock l= new ReentrantLock();
l.lock();
try{
//需同步的代码
}
finally{
l.unlock();
}
这样,就保证了线程的同步。
还有这样一种情况,当同步的代码需要某个条件时,线程才能继续执行。
那就很有可能某一线程获得锁,但是没有条件满足该线程继续运行,那么该线程就白白的浪费了这把锁。
所以,就有一个条件对象来解决这一问题。看下面的代码
Lock l= new ReentrantLock();
Condition cd = l.newCondition(); //生成该锁的条件对象
l.lock();
try{
while( 条件不满足 )
cd.await(); // 使得线程释放该锁,并进入该锁的等待池
//需同步的代码
cd.signalAll(); //唤醒该锁等待池中的所有线程
}
finally{
l.unlock();
}
这样,就实现了对线程的细节控制,使得我们可以精准的控制同步。
除了这个方法,Java中还有另外一种方法,也就是 synchronized 语法。本质上和上面所讲的lock是一样的。
下面同样看一段代码:
synchronized ( obj ) {
//需同步的代码
}
虽然代码简单,但是和第一段代码的效果是一样的。
为了实现条件对象类似的效果,可以使用Object中的wait 和 notify 方法,如下代码:
synchronized ( obj ){
while( 条件不满足 )
wait();
//需同步的代码
notifyAll();
}
效果也同第二段代码一样,所以才说,这两种方法本质上是同一种方法。
---------------
听者有心 原创。