首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中的并发安全队列

Java中的并发安全队列
EN

Stack Overflow用户
提问于 2022-10-13 09:58:44
回答 2查看 56关注 0票数 0

我正在尝试用唯一的元素创建线程安全队列。我没有看到漏洞,但不确定这个实现线程是否安全?get()、add()、toArray()方法在锁下完成所有事情,toString()和equals()使用toArray()来获得主数组副本,并在没有锁的情况下独立工作。

代码语言:javascript
复制
public class SafeQueue<T> {
        private final Object[] queue;
        private final HashSet<T> content;
        private final Lock lock;
        private int size;
        
        public SafeQueue() {
            queue = new Object[100];
            content = new HashSet<>(100);
            lock = new ReentrantLock();
        }

        public boolean add(T el) {
            Objects.requireNonNull(el);
            final Lock lock = this.lock;
            lock.lock();
            try {
               //some logic
            } finally {
                lock.unlock();
            }
            return true;
        }

        public T get() {
            final Lock lock = this.lock;
            lock.lock();
            try {
                T el = (T) queue[0];
                if (el != null) {
                    //some shift logic
                    content.remove(el);
                }
                return el;
            } finally {
                lock.unlock();
            }
        }

        public Object[] toArray() {
            final Lock lock = this.lock;
            lock.lock();
            try {
                return Arrays.copyOf(this.queue, size);
            } finally {
                lock.unlock();
            }
        }

        @Override
        public boolean equals(Object o) {
            Object[] eqQueue = ((SafeQueue<?>) o).toArray();
            Object[] curQueue = toArray();

            //some comparison logic with eqQueue and curQueue
            return equal;
        }

        @Override
        public String toString() {
            Object[] curQueue = toArray();
            StringBuilder sb = new StringBuilder();
            sb.append('[');
            //some logic with curQueue
            return sb.toString();
        }
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-13 15:14:55

您可能想问,对于equals方法来说,线程安全意味着什么?考虑到这一点:

代码语言:javascript
复制
SafeQueue<T> qa = ...;
SafeQueue<T> qb = ...;
...
if (qa.equals(qb)) {
    handleEqualsCase();
}

如果您有任何理由担心equals()方法的线程安全性,那可能是因为其他线程在调用equals()时可能会修改任何队列。

但是,当handleEqualsCase()被调用时,其他线程仍然可以运行,而现在,qaqb都没有被锁定。在调用handleEqualsCase()时,不能保证两个队列仍然相等。但是,如果他们不平等,那肯定是件坏事,对吧?否则,你为什么一开始就费心去测试平等呢?

有一种方法可以解决这个问题。与其编写传统的equals()方法,不如编写如下内容:

代码语言:javascript
复制
private static
boolean unsynchronizedEqualityTest(SafeQueue<T> qa, SafeQueue<T> qb) {
    ...
}

public static
void doIfEqual(SafeQueue<T> qa, SafeQueue<T> qb, Runnable handler) {
    qa.lock.lock();
    qb.lock.lock();
    try {
        if (unsynchronizedEqualityTest(qa, qb)) {
            handler.run();
        }
    } finally {
        qb.lock.unlock();
        qa.lock.unlock();
    }
}

现在,当调用客户端提供的handler时,可以保证两个队列仍然相等,因为它们仍然是锁定的。

但要小心!如果一个线程调用doIfEqual(qa,qb,...),另一个线程调用doIfEqual(qb,qa,...),则可能出现死锁。我让你想办法阻止僵局的发生。

票数 2
EN

Stack Overflow用户

发布于 2022-10-13 10:07:39

是的,您的实现是线程安全的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74053838

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档