Juc并发编程09——自己动手实现排他锁

简介: 我们已经了解了AQS的的基本原理了,不如自己仿照其它锁实现一个排他锁吧。要求如下:同一时间只允许一个线程持有锁,不要求可重入(反复加锁直接忽视即可

我们已经了解了AQS的的基本原理了,不如自己仿照其它锁实现一个排他锁吧。


要求如下:同一时间只允许一个线程持有锁,不要求可重入(反复加锁直接忽视即可)。


(1)实现Lock接口

public class Demo23 {
    public static void main(String[] args) {
    }
    private static class myLock implements Lock{
        @Override
        public void lock() {
        }
        @Override
        public void lockInterruptibly() throws InterruptedException {
        }
        @Override
        public boolean tryLock() {
            return false;
        }
        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }
        @Override
        public void unlock() {
        }
        @Override
        public Condition newCondition() {
            return null;
        }
    }
}


(2) 创建内部类sync继承AQS,内部调用sync完成逻辑


         

上面代码的运行结果如下。


/home/wangzhou/IdeaProjects/jucdemo/src/com/wangzhou/Demo21.java:11:24
java: 未报告的异常错误java.lang.InterruptedException; 必须对其进行捕获或声明以便抛出
1
2

这是因为其父类的tryAcquire方法实现如下。

protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }
1
2
3

(3)实现tryAcquire

先看看其它锁怎么做的。比如公平锁。

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

面代码包含可重入逻辑,我们这里如果重入直接忽略,返回false,因此核心逻辑就只需要进行一个CAS操作了。

@Override
            protected boolean tryAcquire(int acquires) {
                if(isHeldExclusively()) {
                    return true;
                }
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
                return false;
            }


加锁过程已经完成,您可以自行测试,接下来我们来实现解锁功能。


同样先看看其它锁怎么实现。

protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

我们要实现的逻辑也很简单,没加锁的情况下不允许解锁。加锁的情况下解锁。

@Override
            protected boolean tryRelease(int args) {
                if(getState() == 0) {
                    throw new UnsupportedOperationException();
                }
                if(isHeldExclusively()) {
                    setExclusiveOwnerThread(null);
                    setState(0);
                    return true;
                }
                return false;
            }

测试.

public static void main(String[] args) throws InterruptedException {
        myLock lock = new myLock();
        lock.lock();
        new Thread(() ->{
            lock.lock();
            System.out.println("thread2 get lock");
            lock.unlock();
        }).start();
        TimeUnit.SECONDS.sleep(1);
        lock.unlock();
        System.out.println("thread 1 unlock");
相关文章
|
5月前
|
Java
【多线程面试题二十五】、说说你对AQS的理解
这篇文章阐述了对Java中的AbstractQueuedSynchronizer(AQS)的理解,AQS是一个用于构建锁和其他同步组件的框架,它通过维护同步状态和FIFO等待队列,以及线程的阻塞与唤醒机制,来实现同步器的高效管理,并且可以通过实现特定的方法来自定义同步组件的行为。
【多线程面试题二十五】、说说你对AQS的理解
|
3月前
|
安全 Java 程序员
【多线程-从零开始-肆】线程安全、加锁和死锁
【多线程-从零开始-肆】线程安全、加锁和死锁
62 0
|
5月前
|
Java
【多线程面试题二十二】、 说说你对读写锁的了解
这篇文章讨论了读写锁(ReadWriteLock)的概念和应用场景,强调了读写锁适用于读操作远多于写操作的情况,并介绍了Java中`ReentrantReadWriteLock`实现的读写锁特性,包括公平性选择、可重入和可降级。
|
8月前
|
存储 Java
StampedLock(戳记锁)源码解读与使用
StampedLock(戳记锁)源码解读与使用
|
8月前
|
Java
深入理解Java中的并发编程:线程与锁的奥秘
【4月更文挑战第2天】本文将深入探讨Java并发编程的核心概念,包括线程和锁。我们将详细解析线程的生命周期,以及如何通过锁来保证数据的一致性和同步。此外,我们还将讨论一些常见的并发问题,如死锁、活锁和饥饿,以及如何解决这些问题。
|
存储 Java
第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁【Java面试题】
第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁【Java面试题】
68 0
|
8月前
|
安全 Java
大厂面试题详解:synchronized的偏向锁和自旋锁怎么实现的
字节跳动大厂面试题详解:synchronized的偏向锁和自旋锁怎么实现的
82 0
|
8月前
|
安全 Java 数据安全/隐私保护
剑指JUC原理-16.读写锁(下)
剑指JUC原理-16.读写锁
42 0
|
8月前
|
缓存 数据库 容器
剑指JUC原理-16.读写锁(上)
剑指JUC原理-16.读写锁
77 0
|
设计模式 安全 Java
JUC第十二讲:JUC锁 - 看不懂锁核心类 AQS 原理来打我
JUC第十二讲:JUC锁 - 看不懂锁核心类 AQS 原理来打我