16.reentrantreadwritelock이용해서 동기화 개선
ReentrantReadWriteLock이용한 동기화 개선
로드 할 시 임계영역 lock 출력할떄의 lock은 같은 동기화에 묶이는 문제가 발생한다
다른 스레드를 읽고 싶은데 못읽는 비효율적인 경우가 발생하게 된다 키가 같을떄 만약에 아래의 load 하는 스레드가 발생하면 기다리게 된다
1.ReentrantReadWriteLock을 이용한다
- WriteLock이용
private char[] list;
private ReentrantReadWriteLock listLock;// 범위를 좁혀서 lock를 쓸수o index처럼 lock으로 쓸수 없는 데이터 방식
// 전용lock을 쓰므로 기능을 사용하고 싶을때 사용한다 기능:read부분과 writer부분을 나눠서 사용 가능하다
private int index;
private ReentrantLock indexLock;
public CharList3() {
indexLock = new ReentrantLock();
list = new char[240];
listLock = new ReentrantReadWriteLock();
for (int i = 0; i < 240; i++)
list[i] = (char) i;
index = 0;
}
public void load() {
Thread th = Thread.currentThread();
listLock.writeLock().lock();
for (int i = 0; i < 26; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
list[i] = (char) ('A' + i);
}
System.out.printf("%s[%d] : load\n", th.getName(), th.getId());
listLock.writeLock().unlock();
}
public void printAll(int count) {
Thread th = Thread.currentThread();
listLock.writeLock().lock();
for (int i = 0; i < count; i++) {
StringBuilder builder = new StringBuilder();
builder.append(list);
builder.toString();
System.out.printf("%s[%d-%d]:%s\n", th.getName(), th.getId(), ++index, builder.toString());
}
listLock.writeLock().unlock();
}
public void printNext() {
Thread th = Thread.currentThread();
char ch = list[index];
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
return;
}
boolean aquired = indexLock.tryLock();
if (aquired) {
System.out.printf("%s[%d] : index:%d, char: %c\n", th.getName(), th.getId(), index, list[index]);
index++;
indexLock.unlock();
} else {
System.out.printf("%s[%d]: alternater ... \n", th.getName(), th.getId());
}
// }
}
}
sub1[14] : load // 14번이 로드 스레드
sub2[15-1]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2[15-2]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2[15-3]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2[15-4]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
WriterLock는 하나의 스레드만 소유 가능하다
ReadLock는 동시에 여러 스레드를 소유 가능하다
WriterLock이 잠기면 ReadLock을소유한 스레드도 임계영역에 들어 갈 수 없다
WrierLock일 풀리면 Readlock끼리는 동기화 시키지 않는다( 풀리면 readlock이 없는 것처럼 동기화를 시키지 않는다 )
- ReadLock이용(위의 코드 부분 수정)
public void printAll(int count) {
Thread th = Thread.currentThread();
listLock.readLock().lock();
for (int i = 0; i < count; i++) {
StringBuilder builder = new StringBuilder();
builder.append(list);
builder.toString();
System.out.printf("%s[%d-%d]:%s\n", th.getName(), th.getId(), ++index, builder.toString());
}
listLock.readLock().unlock();
}
sub1[14] : load
sub2[15-1]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2[15-2]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2[15-3]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2[15-4]:ABCDEFGHIJKLMNOPQRSTUVWXYZ
Readlock만 하고 싶어도 WrierLock이 잠김으로 기다려야한다
만약 WrierLock일 풀리면서 만약 스레드를 동기화 하지 않을 경우가 발생되면?
기다리는게 없기때문에 읽어들이는 도중에 데이터가 섞여 버린다
따라서 조작을 위한 부분은 ( 줄세우기를 해야하는경우) writer 동기화를 사용한다
읽기을 위한 부분은 readlock 동기화를 사용한다
댓글남기기