码迷,mamicode.com
首页 > 其他好文 > 详细

锁机制

时间:2020-03-25 19:45:19      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:finally   obj   stat   ali   访问   als   void   adl   boolean   

1.锁是干什么用的
  锁一般来说用作资源控制,限制资源访问,防止在并发环境下造成数据错误

2.重入锁
  重入锁也叫作递归锁,指的是同一个线程外层函数获取到一把锁后,内层函数同样具有这把锁的控制权限
  synchronized和ReentrantLock就是重入锁对应的实现
  synchronized重量级的锁 
  ReentrantLock轻量级的锁 lock()代表加入锁 unlock()代表释放锁

  不可重入锁:说明当没有释放该锁时。其他线程获取该锁会进行等待

 

技术图片
public class MyLock {
    //标识锁是否可用  如果值为 true代表有线程正在使用该 锁 ,如果为false代表没有人使用锁
    private boolean isLocked=false;
    //获取锁:加锁
    public synchronized void lock() throws InterruptedException {
        //判断当前该锁是否正在使用
        while (isLocked){
            wait();
        }
        //当前没有人使用情况 下就占用该锁
        isLocked=true;
    }

    //释放锁
    public synchronized  void unLock(){
        //将当前锁资源释放
        isLocked=false;
        //唤起正在等待使用锁的线程
        notify();
    }

}
技术图片

 

技术图片
public class MyLockTest {
MyLock myLock=new MyLock();
    //A业务
    public void print() throws InterruptedException {
        //获取一把锁
        myLock.lock();
        System.out.println("print业务方法");
        doAdd();
        //释放锁
        myLock.unLock();
    }
    //B业务方法
    public void  doAdd() throws InterruptedException {
        //获取一把锁
        myLock.lock();
        System.out.println("aoAdd方法");
        //释放锁
        myLock.unLock();

    }

    public static void main(String[] args) throws InterruptedException {
        MyLockTest myLockTest=new MyLockTest();
        myLockTest.print();
    }
}
技术图片

 

  控制台结果:

当前效果就造成了死锁

技术图片

 

 

 

  synchronized可重入性:如果当前A持有一把锁,在A业务内部调用B,那么B也同样拥有这把锁的使用权限

  编写测试代码:

技术图片
MyLock myLock=new MyLock();
    //A业务
    public synchronized void print() throws InterruptedException {

        System.out.println("print业务方法");
        doAdd();

    }
    //B业务方法
    public synchronized void  doAdd() throws InterruptedException {

        System.out.println("aoAdd方法");


    }

    public static void main(String[] args) throws InterruptedException {
        MyLockTest myLockTest=new MyLockTest();
        myLockTest.print();
    }
技术图片

  控制台结果:

技术图片

 

 

 

  ReentrantLock同样具有可重入性

  编写测试代码:

技术图片
public class MyLockTest {
    //创建锁对象
    Lock lock=new ReentrantLock();
    //A业务
    public void print() throws InterruptedException {
        //获取了一把锁
        lock.lock();
        System.out.println("print业务方法");
        doAdd();
        //释放锁
        lock.unlock();

    }
    //B业务方法
    public void  doAdd() throws InterruptedException {
        //获取一把锁
        lock.lock();
        System.out.println("aoAdd方法");
        //释放锁
        lock.unlock();

    }

    public static void main(String[] args) throws InterruptedException {
        MyLockTest myLockTest=new MyLockTest();
        myLockTest.print();
    }
}
技术图片

  控制台结果:

技术图片

 

 

 

3. 读写锁

  并发线程下,所有线程都执行读的操作,会不会有问题
  并发线程下,部分读部分写会不会有问题 会发生写冲突
  并发线程下,所有线程都执行写会不会有问题 会发生写冲突

 

  编写测试代码:

技术图片
 //创建一个集合
    static Map<String,String> map=new HashMap<String,String>();
    //创建一个读写锁
    static ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
    //获取读锁
    static Lock readLock=lock.readLock();
    //获取写锁
    static Lock writeLock=lock.writeLock();
    //写操作
    public Object put(String key,String value){
        writeLock.lock();
        try {
            System.out.println("Write正在执行写操作~");
            Thread.sleep(100);
            String put = map.put(key, value);
            System.out.println("Write写操作执行完毕~");
            return put;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
        return null;

    }

    //写操作
    public Object get(String key){
        readLock.lock();
        try {
            System.out.println("Read正在执行读操作~");
            Thread.sleep(100);
            String value = map.get(key);
            System.out.println("Read读操作执行完毕~");
            return value;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            readLock.unlock();
        }
        return null;

    }

    public static void main(String[] args) {
        ReadWriteLock lock=new ReadWriteLock();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(()->{
                try {
                    //写操作
                    lock.put(finalI +"","value"+finalI);
                    //读操作
                    System.out.println(lock.get(finalI+""));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

    }
技术图片

  控制台 结果:

我们可以看出是当所有写操作都执行完毕后才开始执行读操作

技术图片

 

4. 乐观锁

  总认为不会发生并发问题,每一次取数据时总认为其他线程不会对该数据先进性更改,但是在更新时会判断其他线程在这之前有

  没有对该数据进行修改,
  数据库当中常用方案:版本号控制

5.悲观锁
  总是假设最坏的情况,每次取数据时,都会认为其他线程会对该数据进行修改,所以会进行加锁
  其他线程访问的时候会阻塞等待,例如在数据库当中可以使用行锁,表锁以及读写锁等方式实现

锁机制

标签:finally   obj   stat   ali   访问   als   void   adl   boolean   

原文地址:https://www.cnblogs.com/tinghao/p/12567786.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!