我正在嘗試創建具有獨特元素的執行緒安全佇列。我沒有看到任何漏洞,但不確定這個實作執行緒是否安全?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();
}
}
uj5u.com熱心網友回復:
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,...)。我會留給你弄清楚如何防止這種僵局發生。
uj5u.com熱心網友回復:
是的,您的實作是執行緒安全的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/517043.html
標籤:爪哇多线程并发
