JUC并发编程(9)--- 一些锁的理解

1、公平锁、非公平锁

公平锁:非常公平,不能插队,先来后到
非公平锁(默认):非常不公平,可以插队
比如:有一个线程需要3s执行结束,另一个3h执行结束,但3h先到。那么对于公平锁,3s必须等3h执行完毕,而对于非公平锁就可以让3s先插队执行。
JUC并发编程(9)--- 一些锁的理解
如上,默认都是非公平,synchronized 和Lock都是默认非公平

2、可重入锁

可重入锁又称递归锁

假设我们进自己家需要一把大门锁,然后拿到大门锁,自然就可以进房间里面
JUC并发编程(9)--- 一些锁的理解
代码演示一下

package com.yx.lock;

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

    public synchronized void sms(){
        System.out.println(Thread.currentThread().getName() + "sms");
        call();//这里也有锁
    }
    public synchronized void call(){
        System.out.println(Thread.currentThread().getName() + "call");
    }
}

线程A调用sms方法时,首先会给sms加锁,然后打印sms,进入call中,自动拿到call的锁,并call打印后,最后再释放所有锁,也就是拿到外面的锁就会自动拿到里面的锁,最后执行完所有的内容,释放锁。

这里用的是synchronized ,我们来看看Lock锁对比一下

3、自旋锁

自旋就是循环,加了一个while语句或者do…while语句。我们来自己实现一个自旋锁,然后用它进行加锁解锁

package com.yx.lock;

import java.util.concurrent.atomic.AtomicReference;

//CAS(CompareAndSet)实现自旋锁
public class SpinLockDemo {

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

    //加锁
    public void myLock(){
        Thread thread = Thread.currentThread();//当前线程
        System.out.println(Thread.currentThread().getName()+"->myLock");

        //不成立就一直循环自旋
        while (!atomicReference.compareAndSet(null,thread)){

        }
    }

    //解锁
    public void myUnLock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"->myUnLock");
        atomicReference.compareAndSet(thread,null);
    }
}

运行下面方法

package com.yx.lock;

import java.util.concurrent.TimeUnit;

public class TestSpinLock {
    public static void main(String[] args) throws InterruptedException {
        SpinLockDemo lock = new SpinLockDemo();

        new Thread(()->{
            lock.myLock();
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.myUnLock();
            }
        },"T1").start();

        TimeUnit.SECONDS.sleep(1);//保证T1线程先拿到锁
        new Thread(()->{
            lock.myLock();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.myUnLock();
            }
        },"T2").start();
    }
}

JUC并发编程(9)--- 一些锁的理解
分析:首先T1线程拿到锁,进入自旋,然后T2也拿到锁,5秒后T1解锁跳出自旋,T2也跟着解锁。注意这个执行的顺序

上一篇:如何在springboot项目中进行XSS过滤


下一篇:PureBasic 打开一个一行有多个数据的文件并读取其中某个数据