几种常见的锁

公平锁:是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到

非公平锁:是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,在高并发的情况下,有可能会造成优先级反转或者饥饿现象。

并发包中ReentrantLock的创建可以指定构造函数的Boolean类型来得到公平锁或非公平锁,默认是非公平锁。

可重入锁:指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取改锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,也就是线程可以进入任何一个他已经拥有的锁同步着的代码块。

class Phone{
    public synchronized void sendSms(){
        System.out.println(Thread.currentThread().getId()+"\t invoked sendSms");
        sendEmail();
    }

    public synchronized void sendEmail(){
        System.out.println(Thread.currentThread().getId()+"\t invoked sendEmail");
    }
}
public class ReenterLockDemo {

    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(()->{
            phone.sendSms();
        },"t1").start();

        new Thread(()->{
            phone.sendEmail();
        },"t2").start();
    }
}

自旋锁:是指尝试获取锁的线程不会立即阻塞,而是采用循环的方法去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU.

public class SpinLockDemo {

    // 原子引用线程
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void myLock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"\t come in");
        while(!atomicReference.compareAndSet(null, thread)){

        }
    }
    public void myUnLock(){
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread, null);
        System.out.println(Thread.currentThread().getName()+"\t invoked myUnLock");
    }
    public static void main(String[] args) throws InterruptedException {

        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(()->{
            spinLockDemo.myLock();
            // 暂停一会
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.myUnLock();
        },"AA").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{
            spinLockDemo.myLock();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.myUnLock();
        },"BB").start();

    }

}

独占锁:指该锁一次只能被一个线程所持有,对ReentrantLock和Synchrnoinzed都是独占锁

共享锁:指该锁可被多个线程所持有,对ReentrantReadWriteLock其读锁是共享锁,写锁是独占锁,该锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。

class MyCache{
    private volatile Map<String,Object> map = new HashMap<>();
    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    public void put(String key, Object value) throws InterruptedException {
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"\t正在写入"+key);
            // 暂停一会线程
            TimeUnit.MILLISECONDS.sleep(300);
            map.put(key, value);
            System.out.println(Thread.currentThread().getName()+"\t 写入完成");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            rwLock.writeLock().unlock();
        }
    }
    public void get(String key){
        rwLock.readLock().lock();
        try{
            System.out.println(Thread.currentThread().getName()+"\t 正在读取");
            try {
                TimeUnit.MILLISECONDS.sleep(300);
            }catch (Exception e){
                e.printStackTrace();
            }
            Object result = map.get(key);
            System.out.println(Thread.currentThread().getName()+"\t 读取完成"+result);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            rwLock.readLock().unlock();
        }
    }
}
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i = 1; i <= 5; i++) {
            final int tempInt = i;
            new Thread(() -> {
                try {
                    myCache.put(tempInt + "", tempInt + "");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
            for (int i = 1; i <= 5; i++) {
                final int tempInt = i;
                new Thread(() -> {
                    myCache.get(tempInt + "");
                }, String.valueOf(i)).start();
            }
        }
    }

发布了254 篇原创文章 · 获赞 18 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36594703/article/details/104435745