您的位置:首页 > 编程语言 > Java开发

关于读写锁算法的Java实现及思考

2012-10-20 16:13 351 查看
问题背景:多个线程对一个共享的资源进行读写访问。写线程之间需要互斥,读线程跟写线程需要互斥,读线程之间不用互斥。

早些时候听张sir的课,讲述java5中增强并发的功能。用java.util.concurrent.locks中ReadWriteLock 可以轻松解决读写锁问题。我在思考如果没有ReadWriteLock,单靠synchronized可以怎样做呢? 的确,比较麻烦。

1.结合张sir传授的面向对象的设计思想,首先设计一个业务类Business作为共享资源,封装write跟read方法。

2.因为write必定互斥,所以直接定义synchronized。

3.read之间不要互斥 所以read 不能直接定义synchronized的 但是 write跟read 需要互斥 如何控制 我想到的一个方法是在read里 加入synchronized(this){} 同时定义readThreads计数器作为信号量 我试想下会出现下面几种情况:

read[m]表示某个线程的read方法 。

write
同上

1>read[m]中执行到synchronized(this){readThreads++;}时 write
来了 write
会被自身的synchronized阻塞。

2>read[m]在do something(此时无锁)时 write
来了 因为 readThreads!=0 而被迫wait。

3> 每次read[m]结束时 wait中的write
会被notify 但如果发现还有其他的read的话 write
只能无奈地再次wait。

4>当readThreads==0并且调用notifyAll 时 read[m] 和 write
会竞争cpu 如果write
再次落败,则会出现1>或3> ; 如果成了,则如下:

5> 如果write
wait中醒来占锁,read[m]被阻塞synchronized(this){readThreads++;}之上。

6>如果被阻塞的write
占锁,read[m]被阻塞synchronized(this){readThreads++;}之上。

从以上看来read 和 write 是互斥的。

4.实现细节如下:<如有错误欢迎指出交流>

package communication;
import java.util.Random;

public class ReadWriteLockTest {
public static void main(String[] args){
final Business business = new Business();

//启动4线程 2读 2写
for(int i=1;i<=2;i++){
new Thread(new Runnable(){
public void run() {
for(int j=1;j<1000;j++){
business.read();
try {
Thread.sleep(900);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();

new Thread(new Runnable(){
public void run() {
Random r = new Random();
for(int j=1;j<1000;j++){
int i = r.nextInt(100);
business.write(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}

}

}
//封装的业务类
class Business{
private int data=0; //共享资源属性
private int readThreads = 0; //读线程数
//private boolean isWriting  = false;
//是否执行写 后来发现不需要 当write抢占锁时 所有的read 都被挡在synchronized (this){}之上 无机会执行wait
public void read(){
synchronized (this) {
/*while(isWriting){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
//readThreads不被锁的话 会出现read和write不互斥的小概率事件 导致线程不安全
readThreads++;

}

System.out.println(Thread.currentThread().getName()+" read begin");
System.out.println(Thread.currentThread().getName()+" read:"+data);
System.out.println(Thread.currentThread().getName()+" read finish");

synchronized (this) {
readThreads--;
this.notifyAll();
}
}

public synchronized void write(int i){
while(readThreads != 0){//当read 正处于do something状态时 来个write 那就只有等等先了
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//isWriting = true;
System.out.println(Thread.currentThread().getName()+" write start");
data = i;
System.out.println(Thread.currentThread().getName()+" write:"+i);
System.out.println(Thread.currentThread().getName()+" write over");
//isWriting = false;
this.notifyAll();
}
}

思考中:

5.当读频繁时 readThreads会长时间!= 0 写线程会饿死 这个可以如何解决?

原文链接:http://www.cnblogs.com/hottea4Goodspeed/archive/2012/03/06/2381257.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Business 设计