我有一個同步練習,我需要同步一個讀取方法,以便任何數量的線程可以執行它,只要沒有寫入方法正在執行。這必須從頭開始,所以我不能使用java.util.concurrent.locks等。Java同步:無阻塞鎖定
爲此,我需要某種機制來防範,但不阻止讀取方法,所以讀取線程被寫入而不是其他讀取阻塞。我不能使用普通的鎖定,因爲在read方法中調用lock方法會導致其他讀取線程等待。當一個線程在write()中時,沒有其他線程必須輸入read()或write() 當一個線程在read()中時,其他線程不必輸入write() ),但他們可能會進入閱讀()
我已經嘗試建立一對自制鎖來處理這個問題。 WriteLock是一個相當標準的reenterant鎖,除了在正在執行讀操作時它會被阻塞(使用讀計數器) 如果遍歷write(),ReadLock應該只會導致線程等待。否則,它應該簡單地允許線程執行其業務並增加WriteLocks計數器。
代碼:
package sync;
public class SyncTest {
Long testlong = new Long(0L);
int reads = 0;
int writes = 0;
WriteLock w = new WriteLock();
ReadLock r = new ReadLock(w);
public SyncTest() {
// TODO Auto-generated constructor stub
}
public static void main(String args[]){
final SyncTest s = new SyncTest();
for(int i = 0 ; i<3 ; i++){ //Start a number of threads to attack SyncTest
final int ifinal = i;
new Thread(){
int inc = ifinal;
@Override
public void run() {
System.out.println("Starting "+inc);
long starttime = System.currentTimeMillis();
try {
while(System.currentTimeMillis()-starttime < 10){
if (inc < 2){
s.readLong();
}else{
s.writeLong(inc+1);
}
}
System.out.println(inc + " done");
if(inc == 0){
Thread.sleep(1000);
System.out.println(s.reads+" "+s.writes);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Thread "+inc+" "+super.toString();
}
}.start();
}
}
public Long readLong() throws InterruptedException{
Long l;
r.lock(); //Lock for reading
//System.out.println("Read "+reads);
l = testlong;
reads++;
r.unlock(); //Unlock after reading
return l;
}
public void writeLong(int i) throws InterruptedException{
w.lock(); //Lock for writing
//System.out.println("Write "+writes);
int curreads = reads;
int curwrites = writes;
testlong = testlong + i;
writes++;
Thread.sleep(100); //Simulate long write
if(curreads != reads){
System.out.println("Reads did not lock");
}
if(curwrites+1 != writes){
System.out.println("Writes did not lock");
}
w.unlock(); //Unlock writing
}
protected class WriteLock{
boolean isLocked = false;
Thread lockedBy = null;
int lockedCount = 0;
int readers = 0; //The number of readers currently through the reading lock.
public synchronized void lock() throws InterruptedException {
System.out.println("Locking: "+Thread.currentThread());
Thread callingThread = Thread.currentThread();
while ((isLocked && lockedBy != callingThread) || readers > 0) { //Wait if locked or readers are in read()
wait();
}
isLocked = true;
lockedCount++;
lockedBy = callingThread;
System.out.println("Is locked: "+Thread.currentThread());
}
public synchronized void unlock() {
//System.out.println("Unlocking: "+Thread.currentThread());
if (Thread.currentThread() == this.lockedBy) {
lockedCount--;
if (lockedCount == 0) {
System.out.println("Is unlocked: "+Thread.currentThread());
isLocked = false;
notify();
}
}
}
}
protected class ReadLock{
WriteLock lock;
public ReadLock(WriteLock lock) {
super();
this.lock = lock;
}
public synchronized void lock() throws InterruptedException { //If write() then wait
System.out.println("Waiting to read: "+Thread.currentThread());
Thread callingThread = Thread.currentThread();
while (lock.isLocked && lock.lockedBy != callingThread) {
wait();
}
lock.readers++; //Increment writelocks readers
System.out.println("Reading: "+Thread.currentThread());
}
public synchronized void unlock() {
lock.readers--; //Subtract from writelocks readers
notify();
}
}
}
這不但是工作,讀鎖的工作原理到目前爲止,它鎖定當一個線程正在寫的讀者,但是當WriteLock解鎖它不釋放出來,據我可以告訴。
這是不是在概念上合理,或者有什麼我不明白與監視器?或者是其他東西?
我會鼓勵你換一個顯示器'嘗試終於{}鎖定你的鎖。如果在鎖定過程中發生任何事情,您的代碼將無法解鎖。 – Gray
非常真實。但這只是一個簡短的編譯,我不想混淆代碼。沒有錯誤被拋出。 –