zoukankan      html  css  js  c++  java
  • 锁机制

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

  • 相关阅读:
    GDI+重绘笔记
    VC++动态链接库(DLL)编程深入浅出(四)
    VC++动态链接库(DLL)编程深入浅出(三)
    VC++动态链接库(DLL)编程深入浅出(二)
    VC++动态链接库(DLL)编程深入浅出(一)
    AOP在 .NET中的七种实现方法
    [c#菜鸟]lambda表达式
    C# IP地址与整数之间的转换
    log4net在xp下不能写日志到mdb,报错Could not load type 'System.Security.Claims.ClaimsIdentity'
    Active Directory 域服务之AD DS 逻辑组件概述
  • 原文地址:https://www.cnblogs.com/liuying23/p/12568513.html
Copyright © 2011-2022 走看看