`

Java中的多线程学习二:线程的同步

阅读更多
---摘自高人
因为多线程,所以我们需要对线程进行一些调度,也就是对线程进行一些处理,防止多线程带来的不同步问题。



在Java中,大的说有两种机制去实现多线程的同步,但是本质上来讲,是一种机制,那就是锁。



首先,是Java中的 java.util.concurrent.locks 中的锁。



这个包中有一个接口 Lock, 有一个类 ReentrantLock 实现了 Lock。



该方法中有一个lock方法,也就是获取锁,一旦某一个线程执行到这个方法,该线程就获得了锁。



如果别的线程如果执行到该方法,而锁已经被另一个线程获取了,则该线程被阻塞,直到获得锁的线程执行到 unlock 方法。



也就是说,如果获得锁的线程没有知道 unlock 方法,则别的线程永远不能运行 lock 和 unlock 之间的代码。



为了保证unlock方法用于被执行,一般都采用如下的格式开发:

Java代码 
1.Lock l= new ReentrantLock();  
2. 
3.l.lock();  
4. 
5.try{  
6.     //需同步的代码  
7.}  
8.finally{  
9.    l.unlock();  
10.} 
Lock l= new ReentrantLock();

l.lock();

try{
     //需同步的代码
}
finally{
    l.unlock();
} 这样,就保证了线程的同步。



还有这样一种情况,当同步的代码需要某个条件时,线程才能继续执行。



那就很有可能某一线程获得锁,但是没有条件满足该线程继续运行,那么该线程就白白的浪费了这把锁。



所以,就有一个条件对象来解决这一问题。看下面的代码

Java代码 
1.Lock l= new ReentrantLock();  
2.Condition cd = l.newCondition();  //生成该锁的条件对象  
3. 
4.l.lock();  
5. 
6.try{  
7.      while( 条件不满足 )  
8.        cd.await();    // 使得线程释放该锁,并进入该锁的等待池  
9. 
10.     //需同步的代码  
11. 
12.        cd.signalAll();   //唤醒该锁等待池中的所有线程  
13.}  
14.finally{  
15.    l.unlock();  
16.} 
Lock l= new ReentrantLock();
Condition cd = l.newCondition();  //生成该锁的条件对象

l.lock();

try{
      while( 条件不满足 )
        cd.await();    // 使得线程释放该锁,并进入该锁的等待池

     //需同步的代码

        cd.signalAll();   //唤醒该锁等待池中的所有线程
}
finally{
    l.unlock();
}这样,就实现了对线程的细节控制,使得我们可以精准的控制同步。



除了这个方法,Java中还有另外一种方法,也就是 synchronized 语法。本质上和上面所讲的lock是一样的。



下面同样看一段代码:

Java代码 
1.synchronized ( obj ) {  
2.     //需同步的代码  
3.} 
synchronized ( obj ) {
     //需同步的代码
}

虽然代码简单,但是和第一段代码的效果是一样的。



为了实现条件对象类似的效果,可以使用Object中的wait 和 notify 方法,如下代码:

Java代码 
1.synchronized ( obj ){  
2.      while( 条件不满足 )  
3.        wait();  
4. 
5.     //需同步的代码  
6. 
7.       notifyAll();  
8.} 
synchronized ( obj ){
      while( 条件不满足 )
        wait();

     //需同步的代码

       notifyAll();
}

效果也同第二段代码一样,所以才说,这两种方法本质上是同一种方法。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics