netty Recycler(四) 多线程回收对象时竞争机制的解决

14 篇文章 0 订阅
11 篇文章 0 订阅
该博客探讨了Netty的Recycler如何处理多线程环境下的对象回收竞争问题。通过分析源码,指出Netty使用`synchronized`关键字确保在设置Stack头时的线程安全,并详细解释了`pushLater`和`newWeakOrderQueue`方法在创建和添加WeakOrderQueue到Stack过程中的作用,以防止数据丢失或竞态条件的发生。
摘要由CSDN通过智能技术生成

假设线程1创建了大量对象,线程2和线程3同时回收线程1的对象,当这两个线程第一次回收对象时会创建WeakOrderQueue,并将其添加到线程1的Stack。多个线程操控一个Stack,这就造成了竞争。那么netty是如何解决竞争?

代码

package study.recycler.again;

import io.netty.util.Recycler;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 断点2 主线程回收池中会有大量CyclerA
 */
public class CycliMutiThread7 {
    private static final Recycler<CyclerA> CyclerRecyclerA = new Recycler<CyclerA>() {
        @Override
        protected CyclerA newObject(Handle<CyclerA> handle) {
            return new CyclerA(handle);
        }
    };
    static final class CyclerA {
        private String value;
        public void setValue(String value) {
            this.value = value;
        }
        private Recycler.Handle<CyclerA> handle;
        public CyclerA(Recycler.Handle<CyclerA> handle) {
            this.handle = handle;
        }
        public void recycle() {
            handle.recycle(this);
        }
    }
    private static final Recycler<CyclerB> CyclerRecyclerB = new Recycler<CyclerB>() {
        @Override
        protected CyclerB newObject(Handle<CyclerB> handle) {
            return new CyclerB(handle);
        }
    };
    static final class CyclerB {
        private String value;
        public void setValue(String value) {
            this.value = value;
        }
        private Recycler.Handle<CyclerB> handle;
        public CyclerB(Recycler.Handle<CyclerB> handle) {
            this.handle = handle;
        }
        public void recycle() {
            handle.recycle(this);
        }
    }
    private static final Recycler<CyclerC> CyclerRecyclerC = new Recycler<CyclerC>() {
        @Override
        protected CyclerC newObject(Handle<CyclerC> handle) {
            return new CyclerC(handle);
        }
    };
    static final class CyclerC {
        private String value;
        public void setValue(String value) {
            this.value = value;
        }
        private Recycler.Handle<CyclerC> handle;
        public CyclerC(Recycler.Handle<CyclerC> handle) {
            this.handle = handle;
        }
        public void recycle() {
            handle.recycle(this);
        }
    }
    public static void  main(String[] args) throws InterruptedException {
        ConcurrentLinkedQueue<CyclerA> qAThread = new ConcurrentLinkedQueue();
        Thread t = Thread.currentThread();

        for (int i = 0; i < 901; ++i) {
            qAThread.add(CyclerRecyclerA.get());
        }

        Thread t1 = new Thread(() -> {
            Thread temp = t;
            CyclerA cyclerA = qAThread.poll();
            cyclerA.setValue("t1");
            cyclerA.recycle();
        });
        t1.start();
        t1.join();

        Thread t2 = new Thread(() -> {
            Thread temp = t;
            CyclerA cyclerA = qAThread.poll();
            cyclerA.setValue("t2");
            cyclerA.recycle();
        });


        t2.start();
        t2.join();


        System.out.println("over");//断点2
    }
}
调用堆栈
setHead:528, Recycler$Stack (io.netty.util)
newQueue:358, Recycler$WeakOrderQueue (io.netty.util)
newWeakOrderQueue:705, Recycler$Stack (io.netty.util)
pushLater:688, Recycler$Stack (io.netty.util)
push:647, Recycler$Stack (io.netty.util)
recycle:236, Recycler$DefaultHandle (io.netty.util)
recycle:27, CycliMutiThread7$CyclerA (study.recycler.again)
lambda$main$0:80, CycliMutiThread7 (study.recycler.again)
run:-1, 440434003 (study.recycler.again.CycliMutiThread7$$Lambda$1)
run:748, Thread (java.lang)
关键代码
        // Marked as synchronized to ensure this is serialized.
        synchronized void setHead(WeakOrderQueue queue) {
            queue.setNext(head);
            head = queue;
        }

由上面代码可以知道,netty中通过synchronized保证多线程安全

此外Recycler中还有Stack中还有两个函数对理解整个流程(创建新的WeakOrderQueue并将其添加到Stack中)比较重要,下面会按照调用顺序讲解

        private void pushLater(DefaultHandle<?> item, Thread thread) {
            if (maxDelayedQueues == 0) {
                // We don't support recycling across threads and should just drop the item on the floor.
                return;
            }

            // we don't want to have a ref to the queue as the value in our weak map
            // so we null it out; to ensure there are no races with restoring it later
            // we impose a memory ordering here (no-op on x86)
            Map<Stack<?>, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get();
            WeakOrderQueue queue = delayedRecycled.get(this);
            if (queue == null) {
                if (delayedRecycled.size() >= maxDelayedQueues) {
                    // Add a dummy queue so we know we should drop the object
                    delayedRecycled.put(this, WeakOrderQueue.DUMMY);
                    return;
                }
                // Check if we already reached the maximum number of delayed queues and if we can allocate at all.
                if ((queue = newWeakOrderQueue(thread)) == null) {
                    // drop object
                    return;
                }
                delayedRecycled.put(this, queue);
            } else if (queue == WeakOrderQueue.DUMMY) {
                // drop object
                return;
            }

            queue.add(item);
        }

比如线程2回收线程1创建的对象,首先会通过对象中注册的DefaultHandler获取对象所属的Stack,然后经过一系列判断进入到pushLater这个函数中并进行下面操作。
线程2第一次回收线程1所创建的对象
1、调用DELAYED_RECYCLED.get()获取一个ThreadLocal对象(如果没有就创建新的)
2、调用newWeakOrderQueue(thread)创建并添加WeakOrderQueue

跟踪newWeakOrderQueue的代码,可以看到WeakOrderQueue的这个函数

static WeakOrderQueue newQueue(Stack<?> stack, Thread thread) {
            // We allocated a Link so reserve the space
            if (!Head.reserveSpaceForLink(stack.availableSharedCapacity)) {
                return null;
            }
            final WeakOrderQueue queue = new WeakOrderQueue(stack, thread);
            // Done outside of the constructor to ensure WeakOrderQueue.this does not escape the constructor and so
            // may be accessed while its still constructed.
            stack.setHead(queue);//上文提到过这个函数,用synchronized修饰过

            return queue;
        }

1、new WeakOrderQueue(stack, thread)创建新的WeakOrderQueue。其中入参thread会存放到WeakOrderQueue.referent
2、上文提到过这个函数,WeakOrderQueue放入Stack中。这个函数用synchronized修饰过,以保证多线程安全。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值