Java Lock机制分析实例

重入锁:Lock有一个实现类 ReentrantLock (又名可重入锁),这种锁是可以反复多次进入的,其局限性在于同一个线程内

public class Lock{
     private boolean isLocked = false;
     public synchronized void lock() throws InterruptedException{
         while(isLocked){    
             wait();  //等待
         }
         isLocked = true;//设为true意思是等待中被锁住
     }
     public synchronized void unlock(){
         isLocked = false;  //意思是解锁
         notify();//唤醒
     }
 }

不可重入锁:又叫自旋锁,只能调用一个锁方法,示例:

 public class Count{
     Lock lock = new Lock();
     public void print(){
         lock.lock();
         doAdd();
         lock.unlock();
     }
     public void doAdd(){
         lock.lock();
         //do something
         lock.unlock();
     }
}

当调用print()方法时,获得了锁,这时就无法再调用doAdd()方法,这时必须先释放锁才能调用,所以称这种锁为不可重入锁,也叫自旋锁


可重入锁:线程可以进入任何一个它已经拥有的锁所同步着的代码块

public class Lock{
      boolean isLocked = false;
      Thread  lockedBy = null;
      int lockedCount = 0;
      public synchronized void lock()
              throws InterruptedException{
          Thread thread = Thread.currentThread();
          while(isLocked && lockedBy != thread){
              wait();
         }
         isLocked = true;
         lockedCount++;
         lockedBy = thread;
     }
     public synchronized void unlock(){
         if(Thread.currentThread() == this.lockedBy){
             lockedCount--;
             if(lockedCount == 0){
                 isLocked = false;
                 notify();
             }
         }
     }
 }

第一个线程执行print()方法,得到线程锁A,使lockedBy等于线程锁A,执行add()方法时,同样要先获取线程锁A,因不满足while循环的(isLocked = false)条件,也就是不等待,继续进行,将此时的lockedCount变量+1,当释放了所有的锁,才执行notify()。如果在执行这个方法时,有第二个线程B想要执行这个方法,因为lockedBy不等于第二个线程,isLocked 为true,导致这个线程B进入了循环,不断执行wait()方法。只有当第一个线程释放了所有的锁,执行了notify()方法,第二个线程B才得以跳出循环,继续执行。


Synchronized、java.util.concurrent.locks.ReentrantLock:都是可重入锁

ReadWriteLock:读写锁,读写锁在读的时候,上读锁,在写的时候,上写锁,这样就很巧妙的解决synchronized的一个性能问题:读与读之间互斥。分成2个锁来分配给线程,从而可以做到读和读互不影响,读和写互斥,写和写互斥,提高读写文件的效率

可中断锁:如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。在Java中,synchronized就不是可中断锁,而Lock是可中断锁。

公平锁:公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。

  非公平锁即无法保证锁的获取是按照请求锁的顺序进行的。这样就可能导致某个或者一些线程永远获取不到锁。

  在Java中,synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。

而对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。设置方法如下:ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);

非公平锁:

猜你喜欢

转载自blog.csdn.net/douxingpeng1/article/details/81748311