我所认识的锁-总结

1、公平锁:多个线程之间可以按照线程申请锁的顺序获取锁;

2、非公平锁:多个线程之间获取锁的顺序不一定按照申请锁的顺序获得;Synchronized、ReentrantLock默认是非公平锁,后者可以通过构造参数获取公平锁。

3、可重入锁又叫递归锁:是指在一个同步方法内部调用另外一个同步方法时,获得的锁是同一把锁,避免死锁;举例如下:

public class TestLock {

    public synchronized void hello() {
        System.out.println(Thread.currentThread().getName() + "\t 测试递归锁");
        //实现的效果就是hello()方法和world()方法总是总一个线程、具有原子性
        world();
    }

    public synchronized void world() {
        System.out.println(Thread.currentThread().getName() + "\t 测试递归锁2");
    }

    public static void main(String[] args) {
        TestLock tl = new TestLock();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                tl.hello();
            }, String.valueOf(i)).start();
        }
    }

}

打印结果:

0	 测试递归锁
0	 测试递归锁2
6	 测试递归锁
6	 测试递归锁2
4	 测试递归锁
4	 测试递归锁2
5	 测试递归锁
5	 测试递归锁2
3	 测试递归锁
3	 测试递归锁2
2	 测试递归锁
2	 测试递归锁2
1	 测试递归锁
1	 测试递归锁2
9	 测试递归锁
9	 测试递归锁2
8	 测试递归锁
8	 测试递归锁2
7	 测试递归锁
7	 测试递归锁2
hello方法和world方法总是一起执行

4、自旋锁:是指获取锁的线程不会立即阻塞,而是利用循环比较的方式去获取锁,好处就是减少上下文切换,缺点是循环比较会消耗cpu的性能,举例如下:

public class TestLock2 {

    //利用在这个原子类中存入当前线程,为获取锁,否则自循环等待其他线程释放锁以获得锁
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void lock() {
        Thread thread = Thread.currentThread();
        //比较替换成功取反为false跳出循环
        while (!atomicReference.compareAndSet(null, thread)) {

        }
        System.out.println(thread.getName() + "\t come in");

    }

    public void unlock() {
        Thread thread = Thread.currentThread();
        //释放锁就是将值为当线程的内存值更新为null,好让下一个线程获取锁
        atomicReference.compareAndSet(thread, null);
        System.out.println(thread.getName() + "\t come out");
    }

    public static void main(String[] args) {
        TestLock2 tl = new TestLock2();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                tl.lock();
                try {
                    //模拟每个线程进来需要消耗1秒钟
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    tl.unlock();
                }
            }, String.valueOf(i)).start();
        }
    }
}

打印结果:

0	 come in
0	 come out
6	 come in
6	 come out
4	 come in
4	 come out
2	 come in
2	 come out
9	 come in
9	 come out
8	 come in
8	 come out
7	 come in
7	 come out
1	 come in
1	 come out
5	 come in
5	 come out
3	 come in
3	 come out

取得了获取锁,释放锁的效果

5、独占锁:一次只能被一个线程拥有;共享锁:一次可以被多个线程共有;其中读读是共享,写读、读写、写写都互斥

举例如下:

public class TestLock3 {

    Map<String, Object> params = new HashMap<>();
    ReentrantReadWriteLock rw = new ReentrantReadWriteLock();

    /**
     * 读共享
     *
     * @param k
     * @return
     */
    public Object get(String k) {
        rw.readLock().lock();
        Object value = null;
        try {
            value = params.get(k);
            System.out.println(Thread.currentThread().getName() + "\t 读到的值" + value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rw.readLock().unlock();
        }
        return value;
    }

    /**
     * 写互斥
     *
     * @param key
     * @param value
     * @return
     */
    public boolean setParams(String key, Object value) {
        rw.writeLock().lock();
        if (value == null) {
            return false;
        }
        try {
            params.put(key, value);
            System.out.println(Thread.currentThread().getName() + "\t key=" + key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rw.writeLock().unlock();
        }
        return true;
    }

    public static void main(String[] args) {
        TestLock3 testLock3 = new TestLock3();
        //多线程写
        for (int i = 0; i < 10; i++) {
            final int a = i;
            new Thread(() -> {
                testLock3.setParams(String.valueOf(a), UUID.randomUUID().toString().substring(0, 3));
            }, String.valueOf(i)).start();
        }

        //先让写线程进行
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //多线程读
        for (int i = 0; i < 10; i++) {
            final int b = i;
            new Thread(() -> {
                testLock3.get(String.valueOf(b));
            }, String.valueOf(i)).start();
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值