公平锁、非公平锁、可重入锁、递归锁、自旋锁 谈谈你的理解?请手写一个自旋锁

  • 公平锁 表示线程获取锁的的顺序是按照线程加锁的顺序来分配的
  • 非公平锁 随机获得

并发包中ReentrantLock 的创建可以指定构造函数的boolean类型来得到公平锁或非公平锁,默认非公平锁。
非公平锁优点是比公平锁吞吐量大
synchronized也是一种非公平锁

可重入锁(又名递归锁):
指的是同一线程外层函数获得锁之后,内层递归函数仍能获得该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁

线程可以进入任何一个他所拥有锁同步着的代码块

可重入锁最大作用是 避免死锁
ReentrantLock 和 synchronized 都是可重入锁

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

//sun.misc.Unsafe
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
    	//var5 = 当前这个对象这个地址上的值是多少
        var5 = this.getIntVolatile(var1, var2);
        //如果当前对象这个地址的值和上面获取的var5一样,就加var4
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
	//修改成功,返回true,跳出循环
	//判断这个值被别人改过了,不是我们获取的期望值了,返回false,继续循环,再获取最新值,直到比较成功
    return var5;
}

模仿写自旋锁:

public class SyncList {

    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void myLock() {
        System.out.println(Thread.currentThread().getName() + "comming in");
        //AA修改后,原子引用有值,不为null,判断不成立,返回false,一直进入循环
        while(! atomicReference.compareAndSet(null, Thread.currentThread())) {

        }
    }

    public void myUnlock() {
        atomicReference.compareAndSet(Thread.currentThread(), null);
        System.out.println(Thread.currentThread().getName() + "invoke myUnlock");
    }

    public static void main(String[] args) {
        SyncList syncList = new SyncList();

        new Thread(() -> {
            syncList.myLock();
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            syncList.myUnlock();
        }, "AA").start();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            syncList.myLock();

            syncList.myUnlock();
        }, "BB").start();
    }
}

AAcomming in
BBcomming in
AAinvoke myUnlock
BBinvoke myUnlock

独占锁(写锁): 该锁一次只能够被一个线程所持有 ReentrantLock/synchronized,ReentrantReadWriterLock 的写锁
共享锁(读锁): 该锁可以被多个线程共有 ReentrantReadWriterLock 的读锁
互斥锁

ReentrantReadWriterLock lock = new ReentrantReadWriterLock();
...
lock.readLock().lock(); //获取读锁
... //允许多个线程同时进入lock()后面的代码
lock.readLock.unLock();
lock.writeLock().lock(); //获取写锁
... //同一时间只允许一个线程执行lock()后面的代码
lock.writeLock().unLock();

读写锁互斥例子:

class MyCache{
    private volatile Map<String, Object> map = new HashMap<>();
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void put(String key, Object value) {
        try {
            lock.writeLock().lock();
            System.out.println(Thread.currentThread().getName() + " put key:" + key + " value:" + value);
            TimeUnit.SECONDS.sleep(2);
            map.put(key, value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public void get(String key) {
        try {
            lock.readLock().lock();
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName() + " get key:" + key + " value:" + map.get(key));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
    }
}

public class Lock {

    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                myCache.put(finalI +"", finalI +"");
            }, "put" + String.valueOf(i)).start();
        }

//        try {
//            TimeUnit.SECONDS.sleep(2);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                myCache.get(String.valueOf(finalI));
            }, "getA" + String.valueOf(i)).start();
        }

        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                myCache.get(String.valueOf(finalI));
            }, "getB" + String.valueOf(i)).start();
        }
    }
}



put0 put key:0 value:0
put1 put key:1 value:1
put2 put key:2 value:2
put3 put key:3 value:3
put4 put key:4 value:4
getA0 get key:0 value:0
getB3 get key:3 value:3
getB4 get key:4 value:4
getA2 get key:2 value:2
getA1 get key:1 value:1
getB2 get key:2 value:2
getB1 get key:1 value:1
getB0 get key:0 value:0
getA4 get key:4 value:4
getA3 get key:3 value:3
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值