JUC之手写Lock锁(aqs+cas+LockSupport)

Lock 锁是一种可重入的、线程安全的同步机制,它提供了比 synchronized 更高级的功能和灵活性。

Lock 锁的实现原理:

Lock 锁的实现原理主要是基于 Java 中的 AQS(AbstractQueuedSynchronizer)框架来实现的。AQS 是 Java 中实现同步器的基础框架,它通过内置的队列来管理等待队列中的线程,以及维护锁的状态信息。 底层基于AQS+Cas+LockSupport锁实现的优点是具有良好的性能和可伸缩性,同时支持可重入、可中断、可限时等待等高级特性,适用于各种并发场景。缺点是实现比较复杂,需要考虑多线程同步和竞争情况,容易引入死锁等问题。

AQS(AbstractQueuedSynchronizer)是一个抽象类,AQS中 维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。

这里volatile能够保证多线程下的可见性,当state=1则代表当前对象锁已经被占有,其他线程来加锁时则会失败,加锁失败的线程会被放入一个FIFO的等待队列中,比列会被UNSAFE.park()操作挂起,等待其他获取锁的线程释放锁才能够被唤醒。

另外state的操作都是通过CAS来保证其并发修改的安全性。

 

CAS(Compare And Swap)是一种无锁算法,用于实现并发环境下的原子操作。CAS 操作包含三个参数:需要修改的内存位置 V、原始值 A、新值 B。只有当当前内存位置的值等于原始值 A 时,才将内存位置的值修改为新值 B,并返回 true;否则不做任何操作,并返回 false。

CAS 原理如下:

  1. 获取需要修改的内存位置 V 的当前值 old。
  2. 判断当前值 old 是否等于原始值 A,如果相等,则将内存位置的值设置为新值 B,否则不做任何操作。
  3. 返回修改结果 true 或 false。

整个 CAS 操作是原子的,即在 CAS 操作过程中,其他线程不能对该内存位置进行修改。

CAS 操作属于乐观锁,因为它假设共享数据不会被其他线程修改,从而避免了使用互斥锁带来的开销和竞争。但是如果多个线程同时执行 CAS 操作,只有一个线程的操作能够成功,其他线程需要重试,这可能会导致一些性能问题。

Java 中的 AtomicInteger、AtomicLong、AtomicReference 等类都是基于 CAS 操作实现的,可以提供一定的线程安全性。CAS 操作在 Java 并发编程中广泛应用,例如实现自旋锁、非阻塞算法等。

LockSupport是一个线程阻塞工具类。

了解完这些下面让我们来使用代码实现一下吧。

代码实现:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Collectors;


/**
 * 手写简易lock锁:底层基于(AQS队列式同步器)+(Cas算法)+(LockSupport线程阻塞工具类)实现
 */
public class SimpleLock {
    /**
     * 锁的状态 0===没有线程获取到锁 1表示已经有线程获取到锁
     */
    private AtomicInteger lockState = new AtomicInteger(0);
    /**
     * 获取到锁的线程
     */
    private Thread getLockThread = null;
    /**
     * 无边界并发队列:用来存储没有获取到锁的线程
     */
    private ConcurrentLinkedDeque<Thread> concurrentLinkedDeque = new ConcurrentLinkedDeque<Thread>();

    /**
     * 获取锁
     */
    public void lock() {
        acquire();
    }

    public boolean acquire() {
        for (; ;) {
            System.out.println(Thread.currentThread().getName()+"cas操作");
            if (compareAndSet(0, 1)) {
                // 获取锁成功
                getLockThread = Thread.currentThread();
                return true;
            }
            // 获取锁失败
            Thread thread = Thread.currentThread();
            concurrentLinkedDeque.add(thread);
            // 阻塞
            LockSupport.park();
        }
    }

    private boolean compareAndSet(int expect, int update) {
        return lockState.compareAndSet(expect, update);
    }

    /**
     * 释放锁
     */
    public boolean unLock() {
        if (getLockThread == null) {
            return false;
        }
        if (getLockThread == Thread.currentThread()) {
            boolean result = compareAndSet(1, 0);
            if (result) {
                // 公平锁唤醒:
                Thread first = concurrentLinkedDeque.pollFirst();
                if (first!=null) {
                    System.out.println(first.getName()+",被唤醒");
                    LockSupport.unpark(first);
                }
                // 非公平锁
            }
        }

        return false;
    }
}

class Test{
    public static void main(String[] args) throws InterruptedException {
        SimpleLock simpleLock = new SimpleLock();
        simpleLock.lock();
        for (int i=0;i<1;i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "start");
                simpleLock.lock();
                System.out.println(Thread.currentThread().getName() + "end");
                simpleLock.unLock();
            }).start();
        }
        Thread.sleep(1000);
        simpleLock.unLock();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值