一、 synchronized的缺陷

当一个代码块被synchronized修饰时,同时该代码块被一个线程执行,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:

 1)获取锁的线程执行完成代码块,自动释放锁资源

 2)代码块中执行异常,由jvm释放锁资源

 如果在执行代码块时候,一个线程在代码块执行过程中Thread.sleep() 睡眠  线程被阻塞了,其他线程只能等待当前线程执行完成后才能执行。及其浪费效率。

另外当多个线程在执行写与写操作时,会发生线程冲突,但当多个线程用于读操作,其中一个线程读取占用的锁资源  而其他线程只能等待造成浪费资源。

通过多个线程读取操作线程不会冲突,通过lock可以实现。

不同点:

   synchronized是java内置的,是java关键字,lock 是一个接口  不是内置的通过这个接口可以实现同步访问

   synchronized不需要用户手动释放锁资源,当同步方法或者同步代码块执行完成后,系统会自动让线程释放锁资源。而Lock必须要手动释放锁资源,如果不释放会出现死锁

二、 java.util.concurrent.locks包下常用的类

 1) Lock 是一个接口

     提供了六个方法

     void lock();    boolean tryLock(); boolean tryLock(long time,timeUnit unit); void  lockInteruptibly(); contition newContition()  void unlock();

    其中lock()  tryLock()   tryLock(long time,timeUnit unit)  lockInteruptibly() 用于获取锁    unlock() 用于释放锁

     由于采用lock  不会自动释放锁,需要手动释放锁  所以采用lock 必须在try{}catch(){}finally{}异常捕获中进行,在finally中释放锁

    lock()是最常用的获取锁的方式

     例子:

       Lock lock = ..

       lock.lock();

      try{

   }catch(Exception e){

         }finally{

    lock.unlock()

  }

   

    tryLock 尝试获取锁,如果获取到返回true 如果获取不到返回false   不会拿不到锁一致在等待

    tryLock(long time,TimeUnit unit) 与tryLock()一样都是尝试获取锁,如果获取到返回true  否则返回false  区别在于tryLock(long time ,TimeUnit unit)会等待一定时间,如果直接获取到锁返回true 或者在设置的等待时间内获取到锁返回true  否则返回flase

    Lock lock = ..

    if(lock.tryLock()){

  try{

  }catch(){

      }finally{

   lock.unlock(); 

     }

 }

    lockInterruptibly() 可以用来获取锁,但是如果在获取的锁已经被其他线程锁占用  在等待过程中可以中断当前线程的等待状态。通俗的将  如果 a  b两个线程通过Lock.lockInterruptibly()获取某一个锁时,如果a先获取到了锁   b处于等待状态 那么b可以调用b.interrup()方法中断b的等待状态

  由于lockInterruptibly()的声明中抛出了异常,所以lock.lockInterruptibly()必须放在try块中或者在调用lockInterruptibly()的方法外声明抛出InterruptedException。

   public void method () throws InterruptedException{

  lock.Interruptibly();

       try{

  }catch(){

      }finally{

       lock.unlock();

     }

 }

  当一个线程获取到了锁 是不会被interrup()方法中断  只有处于等待状态的线程在才能被中断。

2)ReentrantLock  可重入锁

    ReentrantLock是Lock接口的唯一实现类

    Lock 接口的实现方式:

  

package cn.ac.bcc.lock;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
    
    private List<Integer> list = new ArrayList<>();

    
    public static void main(String[] args) {
        
        //实例化当前类对象
        final LockDemo ld = new LockDemo();
        //创建两个线程对象  调用insert方法
         new Thread(new Runnable(){
            @Override
            public void run() {
                
              ld.insert(Thread.currentThread());

            }
            
        }).start();
         
         new Thread(new Runnable(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                ld.insert(Thread.currentThread());
            }
             
         }).start();
    }
    
    public void insert(Thread thread){
        
        //创建局部lock锁对象
        Lock lock = new ReentrantLock();
        System.out.println(lock);
        //获取锁
        lock.lock();
        try {
            for(int i=0;i<5;i++){
                list.add(i);
            }
            System.out.println(Thread.currentThread().getName()+"获取了锁");
        } catch (Exception e) {
            // TODO: handle exception
        }finally{
            //释放锁
            lock.unlock();
            System.out.println(Thread.currentThread().getName()+"释放了锁");
        }
    }

}
View Code

相关文章: