我正在尝试用唯一的元素创建线程安全队列。我没有看到漏洞,但不确定这个实现线程是否安全?get()、add()、toArray()方法在锁下完成所有事情,toString()和equals()使用toArray()来获得主数组副本,并在没有锁的情况下独立工作。
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();
}
}发布于 2022-10-13 15:14:55
您可能想问,对于equals方法来说,线程安全意味着什么?考虑到这一点:
SafeQueue<T> qa = ...;
SafeQueue<T> qb = ...;
...
if (qa.equals(qb)) {
handleEqualsCase();
}如果您有任何理由担心equals()方法的线程安全性,那可能是因为其他线程在调用equals()时可能会修改任何队列。
但是,当handleEqualsCase()被调用时,其他线程仍然可以运行,而现在,qa和qb都没有被锁定。在调用handleEqualsCase()时,不能保证两个队列仍然相等。但是,如果他们不平等,那肯定是件坏事,对吧?否则,你为什么一开始就费心去测试平等呢?
有一种方法可以解决这个问题。与其编写传统的equals()方法,不如编写如下内容:
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,...),则可能出现死锁。我让你想办法阻止僵局的发生。
发布于 2022-10-13 10:07:39
是的,您的实现是线程安全的。
https://stackoverflow.com/questions/74053838
复制相似问题