读写锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import java.util.Random;
class Data {
private final char[] buffer;
private final ReadWriteLock lock = new ReadWriteLock();
Data(int size) {
this.buffer = new char[size];
for(int i = 0; i < size; i++) {
buffer[i] = '*';
}
}
char[] read() throws InterruptedException {
lock.readLock();
try {
return doRead();
} finally {
lock.readUnlock();
}
}
void write(char c) throws InterruptedException {
lock.writeLock();
try {
doWrite(c);
} finally {
lock.writeUnlock();
}
}
private char[] doRead() {
char[] newBuffer = new char[buffer.length];
System.arraycopy(buffer, 0, newBuffer, 0, newBuffer.length);
slowly();
return newBuffer;
}
private void doWrite(char c) {
for(int i = 0; i < buffer.length; i++) {
buffer[i] = c;
slowly();
}
}
private void slowly() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class WriterThread extends Thread {
private static final Random random = new Random();
private final Data data;
private final String filler;
private int index = 0;
WriterThread(Data data, String filler) {
this.data = data;
this.filler = filler;
}
@Override
public void run() {
try {
while(true) {
char c = nextChar();
data.write(c);
Thread.sleep(random.nextInt(3000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private char nextChar() {
if(index >= filler.length()) {
index = 0;
}
char c = filler.charAt(index);
index++;
return c;
}
}
class ReaderThread extends Thread {
private final Data data;
ReaderThread(Data data) {
this.data = data;
}
@Override
public void run() {
try {
while(true) {
char[] readBuffer = data.read();
System.out.println(Thread.currentThread().getName() + " read " + String.valueOf(readBuffer));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ReadWriteLock {
private int readingReaders = 0;
private int waitingWriters = 0;
private int writingWriters = 0;
private boolean preferWriter = true;
synchronized void readLock() throws InterruptedException {
while(writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
wait();
}
readingReaders++;
}
synchronized void readUnlock() {
readingReaders--;
preferWriter = true;
notifyAll();
}
synchronized void writeLock() throws InterruptedException{
waitingWriters++;
try {
while(readingReaders > 0 || writingWriters > 0) {
wait();
}
} finally {
waitingWriters--;
}
writingWriters++;
}
synchronized void writeUnlock() {
writingWriters--;
preferWriter = false;
notifyAll();
}
}
public class Test {
public static void main(String[] args) {
var data = new Data(10);
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new WriterThread(data, "ABCDEF").start();
new WriterThread(data, "abcdef").start();
}
}