概述
概述
在多线程的情况下访问共享资源,需要对资源进行同步操作以防止数据不同步的情况发生,通常我们用synchronized关键字或显氏锁。
对资源的访问一般包括两种类型的动作,读和写。如果多个线程在某个时刻对资源进行读操作,这时用排他的方式加锁,就显得简单粗暴,降低执行效率。如果的某个资源的读操作多于写操作,那么读时不加锁,很明显能很好地提升性能。
多线程访问concern和conflict
线程 | 读 | 写 |
---|---|---|
读 | 不冲突 | 冲突 |
写 | 冲突 | 冲突 |
共享资源在多个线程中同时进行读操作不会引起冲突
ReadWriteLock
public class ReadWriteLock {
//正在读的读线程
private int readingReaders=0;
//正在等待的读线程
private int waitingReaders=0;
//正在写的写进程
private int writingWriters=0;
//正在等待的写进程
private int waitingWriters=0;
//是否倾向写进程
private static boolean preferWriter=true;
public ReadWriteLock() {
this(preferWriter);
}
public ReadWriteLock(boolean preferWriter) {
this.preferWriter=preferWriter;
}
public synchronized void readLock() {
this.waitingReaders++;
try {
//如果有正在写的写线程或者读写锁倾向写进程且有等待的写线程则wait
while(writingWriters>0 ||(preferWriter && waitingWriters>0)) {
this.wait();
}
this.readingReaders++;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
this.waitingReaders--;
}
}
public synchronized void readUnlock() {
this.readingReaders--;
this.notifyAll();
}
public synchronized void writeLock() {
this.waitingWriters++;
try {
//如果有正在读的线程或者正在写的写线程
while(readingReaders>0 || writingWriters>0) {
this.wait();
}
this.writingWriters++;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
this.waitingWriters--;
}
}
public synchronized void writeUnlock() {
this.writingWriters--;
this.notifyAll();
}
}
SharedResource
public class SharedResource {
private final char[] buffer;
private final ReadWriteLock lock =new ReadWriteLock();
public SharedResource(int size) {
this.buffer=new char[size];
for(int i=0;i<size;i++) {
buffer[i]='*';
}
}
//读操作
public char[] read() {
try {
lock.readLock();
return this.doRead();
}finally {
lock.readUnlock();
}
}
//写操作
public void write(char data) {
try {
lock.writeLock();
this.doWrite(data);
}finally {
lock.writeUnlock();
}
}
//返回副本
private char[] doRead() {
char[] copyBuffer= new char[buffer.length];
System.arraycopy(buffer, 0,copyBuffer,0,buffer.length);
slowly(100);
return copyBuffer;
}
private void doWrite(char data) {
for(int i=0;i<buffer.length;i++) {
buffer[i]=data;
}
slowly(50);
}
private void slowly(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ReadWorker
public class ReadWorker extends Thread{
private final SharedResource resource;
public ReadWorker(SharedResource resource) {
this.resource=resource;
}
@Override
public void run() {
char readBuf[];
try {
while(true) {
readBuf=resource.read();
System.out.println(Thread.currentThread().getName()+":"+String.valueOf(readBuf));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
WriteWorker
public class WriteWorker extends Thread{
private final SharedResource resource;
private static final Random random =new Random(System.currentTimeMillis());
private final String string;
private int index=0;
public WriteWorker(SharedResource resource,String string) {
this.resource=resource;
this.string=string;
}
@Override
public void run() {
try{
while(true) {
char c=nextchar();
resource.write(c);
Thread.sleep(random.nextInt(1000));
}
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private char nextchar() {
char c=string.charAt(index);
index++;
if(index>=string.length()) {
index=0;
}
return c;
}
}
测试类
public static void main(String[] args) {
SharedResource sharedResource = new SharedResource(10);
ReadWorker readWorker = new ReadWorker(sharedResource);
WriteWorker writeWorker = new WriteWorker(sharedResource, "Reyco");
readWorker.start();
}
最后
以上就是老迟到外套为你收集整理的玩转并发-多线程读写锁分离设计模式的全部内容,希望文章能够帮你解决玩转并发-多线程读写锁分离设计模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复