美文网首页
Java AQS 自定义同步类

Java AQS 自定义同步类

作者: 折剑游侠 | 来源:发表于2021-09-26 14:57 被阅读0次

    分析完了AQS原理,下面借助AQS实现一个同步类,然后用这个同步类写一下经典的三个线程循环打印。就决定叫它BLock

    对于BLock而言只需要对外提供两个方法lock()unlock(),那么AQS的具体实现可以模仿ReentrantLock托管给内部类Sync

    class BLock {
        private val sync = Sync()
    
        fun lock() {
            sync.lock()
        }
    
        fun unlock() {
            sync.unlock()
        }
    
        private inner class Sync : AbstractQueuedSynchronizer() {
            fun lock() = acquire(1)
    
            override fun tryAcquire(arg: Int): Boolean {
                return true
            }
    
            fun unlock() {
                release(1)
            }
    
            override fun tryRelease(arg: Int): Boolean {
                return true
            }
        }
    }
    

    lock()默认请求一个资源acquire(1);unlock()对应释放资源release(1)。接下来分别实现tryAcquire()tryRelease()实现资源控制,也就是state的值啦。

    tryAcquire()

            override fun tryAcquire(arg: Int): Boolean {
                val s = state
                if (s == 0) {
                    if (compareAndSetState(0, arg)) {
                        exclusiveOwnerThread = currentThread
                        return true
                    }
                }
                return false
            }
    

    获取当前state:

    • 为0表示锁已被释放,cas改为1成功后标识currentThread然后返回true
    • 其它情况下返回false

    但是这样忽略了可重入的逻辑,有可能当前线程持有了锁又再次获取锁,问题不大加个if else

            override fun tryAcquire(arg: Int): Boolean {
                val currentThread = Thread.currentThread()
                val s = state
                if (s == 0) {
                    if (compareAndSetState(0, arg)) {
                        exclusiveOwnerThread = currentThread
                        return true
                    }
                } else if (currentThread === exclusiveOwnerThread) {
                    val next = s + arg
                    state = next
                    return true
                }
                return false
            }
    

    state为1时判断当前线程是否已经获取了锁currentThread === exclusiveOwnerThread,已获取state继续+1,由此可知lock()了几次unlock()也要对应调用才能释放锁。

    tryRelease()

            override fun tryRelease(arg: Int): Boolean {
                val c: Int = state - arg
                if (Thread.currentThread() !== exclusiveOwnerThread) throw IllegalMonitorStateException()
                var free = false
                if (c == 0) {
                    free = true
                    exclusiveOwnerThread = null
                }
                state = c
                return free
            }
    

    state减去1

    • check当前线程是否获取了锁
    • state为0释放锁,currentThread置为null
    • state不为0返回false

    写下来其实和ReentrantLock非公平锁的实现差不太多,接下来用BLock实现三个线程循环打印。

        private fun initThread() {
            val lock = BLock()
            var count = 0
            val maxCount = 100
            Thread A@{
                while (true) {
                    lock.lock()
                    if (count > maxCount) {
                        lock.unlock()
                        return@A
                    }
                    if (count % 3 == 0) {
                        Log.d("chenxuan----->", "A-$count")
                        count++
                    }
                    lock.unlock()
                }
            }.start()
    
            Thread B@{
                while (true) {
                    lock.lock()
                    if (count > maxCount) {
                        lock.unlock()
                        return@B
                    }
                    if (count % 3 == 1) {
                        Log.d("chenxuan----->", "B-$count")
                        count++
                    }
                    lock.unlock()
                }
            }.start()
    
            Thread C@{
                while (true) {
                    lock.lock()
                    if (count > maxCount) {
                        lock.unlock()
                        return@C
                    }
                    if (count % 3 == 2) {
                        Log.d("chenxuan----->", "C-$count")
                        count++
                    }
                    lock.unlock()
                }
            }.start()
        }
    

    check下log


    log.png

    相关文章

      网友评论

          本文标题:Java AQS 自定义同步类

          本文链接:https://www.haomeiwen.com/subject/ylhqnltx.html