понедельник, 21 апреля 2008 г.

WriteLock

Сегодня наколбасил небольшую блокировочку на Java. Предназначена для случаев, когда процент изменений мал по сравнению с процентом доступа к данным. В таком случае применение этой блокировки целесообразно. Блокировка позволяет работать многим потокам для чтения, но не позволяет работать многим потокам для записи. Кроме того, исключает работу читателей во время работы писателя. Иными словами в критическом участке работают либо много читателей, либо только один писатель.

Вот этот тест предназначен для тестирования этой блокировки:



package javaapplication13;

/**
*
* @author cy6ergn0m
*/
public class Main {

static class ReaderThread extends Thread {

@Override
public void run () {
try {
for( int i = 0; i < 1000; ++i ) {
wl.beginRead();
int now = safeObject;
sleep( 50 );
if( now != safeObject ) {
System.err.println( "safe object damaged!" );
System.err.flush();
System.exit( -1 );
}
wl.endRead();
}
} catch ( InterruptedException ex ) {
ex.printStackTrace();
}
}

}

static class WriterThread extends Thread {

@Override
public void run () {
try {
for( int i = 0; i < 1000; ++i ) {
wl.beginWrite();
safeObject++;
wl.endWrite();
}
} catch ( InterruptedException ex ) {
ex.printStackTrace();
}
}

}

static final WriteLock wl = new WriteLock(false);
static int safeObject = 0;
public static void main(String[] args) throws InterruptedException {
Thread ths[] = new Thread[ 3000 ];
for( int i = 0; i < ths.length; ++i ) {
if( (i & 1) == 0 )
ths[i] = new ReaderThread();
else
ths[i] = new WriterThread();
ths[i].setPriority( Thread.MIN_PRIORITY );
}

for( Thread th : ths )
th.start();

for( Thread th : ths )
th.join();
}

}




А вот собственно сам код блокировки


package cy6ergn0m;

/**
* WriteLock is a two way lock. Expected to be used by two types of threads.
* First type: readers. Readers threads can work at the same time.
* Second type: writers. Writers can't work simultaneously.
* At any time in critical section can work many readers
* or only one writer.
* WriteLock has one parameter: aggressiveExclusion. This is a flag.
* If aggressiveExclusion is true, all readres waits while all writers will
* be done, if false, writer will wait until readers attempts to enter section.
* It looks like priority. If true, writers has greather priority, if false,
* readres has greather priority.
*
* @author cy6erGn0m <cy6erGn0m@gmail.com>
*/
public class WriteLock {
private final boolean aggressiveExclusion;
private Object lock = new Object();
private boolean writeNow = false;
private int writePendings = 0;
private int readers = 0;

/**
* sets aggressiveExclusion = true
*/
public WriteLock () {
aggressiveExclusion = true;
}

public WriteLock ( boolean aggressiveExclusion ) {
this.aggressiveExclusion = aggressiveExclusion;
}

public void beginWrite() throws InterruptedException {
synchronized( lock ) {
writePendings++;
while( writeNow || readers > 0 )
lock.wait();
writeNow = true;
writePendings--;
}
}

public void endWrite() {
synchronized( lock ) {
if( !writeNow )
throw new IllegalStateException( "notin write section" );
writeNow = false;
lock.notifyAll();
}
}

public void beginRead() throws InterruptedException {
synchronized( lock ) {
while( writeNow || (aggressiveExclusion && writePendings > 0 ) )
lock.wait();
readers++;
}
}

public void endRead() {
synchronized( lock ) {
readers--;
lock.notifyAll();
}
}
}

Комментариев нет: