zoukankan      html  css  js  c++  java
  • java面试-公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解

    一、公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解

    公平锁:多个线程按照申请的顺序来获取锁。

    非公平锁:多个线程获取锁的先后顺序与申请锁的顺序无关。【ReentrantLock 默认非公平、synchronized】

    总结:非公平锁的吞吐量比公平锁大。

    可重入锁(又名递归锁):线程可以进入任何一个它已经获取锁的同步代码块中。

    可重入锁的最大作用:避免死锁

    自旋转:是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁。

    好处:减少线程上下文切换的消耗,

    缺点:循环会消耗CPU

    二、请手写一个自旋锁

    /**
     * Created by wujuhong on 2019/1/14.
     * 通过AtomicReference可实现简单的自旋
     */
    public class SpinLock {
    
        //原子引用线程
        private AtomicReference<Thread> atomicReference = new AtomicReference<>();
    
        //让当前想要获取锁的线程做几个空循环
        public void mylock() {
            Thread currentThread = Thread.currentThread();
            System.out.println(Thread.currentThread().getName()+" come in");
            while (!atomicReference.compareAndSet(null, currentThread)) {
    
            }
        }
    
    
        public void myunlock() {
            Thread currentThread = Thread.currentThread();
            atomicReference.compareAndSet(currentThread, null);
            System.out.println(Thread.currentThread().getName()+" invoked myunlock");
    
        }
    
        public static void main(String[] args) {
            SpinLock spinLock = new SpinLock();
            new Thread(() -> {
                spinLock.mylock();
    
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                spinLock.myunlock();
            },"AA").start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> {
                spinLock.mylock();
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                spinLock.myunlock();
            },"BB").start();
    
        }
    }
    

      

    三、ReentrantReadWriteLock读写锁

    • 允许多个线程同时读共享变量
    • 只允许一个线程写共享变量
    • 如果一个写线程正在执行写操作,此时禁止读线程读共享变量

    说明:锁升级不允许,锁降级允许

    public class ReadWriteLockDemo {
    
        //写操作:原子+独占,整个过程必须是一个完整的统一体,中间不许被分割,被打断。
        public static void main(String[] args) {
            MyCache myCache = new MyCache();
            for (int i = 0; i <= 5; i++) {
                final int tempInt = i;
                new Thread(() -> myCache.put(tempInt + "", tempInt), String.valueOf(i)).start();
            }
    
            for (int i = 0; i <= 5; i++) {
                final int tempInt = i;
                new Thread(() -> myCache.get(tempInt + ""), String.valueOf(i)).start();
            }
        }
    
    }
    
    
    class MyCache {
        private volatile Map<String, Object> map = new HashMap<>();
        
        private ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
    
        public void put(String key, Object value) {
            rwlock.writeLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 正在写入" + key);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                map.put(key, value);
                System.out.println(Thread.currentThread().getName() + " 写入完成");
    
            } finally {
                rwlock.writeLock().unlock();
            }
    
    
        }
    
    
        public void get(String key) {
            rwlock.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 正在读取");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Object result = map.get(key);
                System.out.println(Thread.currentThread().getName() + " 读取完成" + result);
            } finally {
                rwlock.readLock().unlock();
            }
    
    
        }
    }
    

      

  • 相关阅读:
    检测后缀表达式的合法性
    对表达式进行空白符预处理
    字符串替换
    中缀表达式的计算
    Linux shell编程
    Linux常用shell
    [转载]shell脚本编写规范
    [转载]Linux文件类型
    Linux的进程
    Linux进入命令行模式
  • 原文地址:https://www.cnblogs.com/wjh123/p/11117932.html
Copyright © 2011-2022 走看看