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

开发 后端 算法
问题背景:多个线程对一个共享的资源进行读写访问。写线程之间需要互斥,读线程跟写线程需要互斥,读线程之间不用互斥。

问题背景:多个线程对一个共享的资源进行读写访问。写线程之间需要互斥,读线程跟写线程需要互斥,读线程之间不用互斥。

早些时候听张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[n] 同上

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

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

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

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

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

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

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

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

  1. package communication;  
  2. import java.util.Random;  
  3.  
  4. public class ReadWriteLockTest {  
  5.         public static void main(String[] args){  
  6.                 final Business business = new Business();  
  7.                   
  8.                 //启动4线程 2读 2写  
  9.                 for(int i=1;i<=2;i++){  
  10.                                 new Thread(new Runnable(){  
  11.                                         public void run() {  
  12.                                                 for(int j=1;j<1000;j++){  
  13.                                                         business.read();  
  14.                                                         try {  
  15.                                                                 Thread.sleep(900);  
  16.                                                         } catch (InterruptedException e) {  
  17.                                                                 e.printStackTrace();  
  18.                                                         }                                                          
  19.                                                 }                                          
  20.                                         }                                  
  21.                                 }).start();  
  22.                                   
  23.                                 new Thread(new Runnable(){  
  24.                                         public void run() {  
  25.                                                 Random r = new Random();  
  26.                                                 for(int j=1;j<1000;j++){  
  27.                                                         int i = r.nextInt(100);  
  28.                                                         business.write(i);  
  29.                                                         try {  
  30.                                                                 Thread.sleep(1000);  
  31.                                                         } catch (InterruptedException e) {  
  32.                                                                 e.printStackTrace();  
  33.                                                         }  
  34.                                                 }                                          
  35.                                         }                  
  36.                                 }).start();  
  37.                 }  
  38.                   
  39.         }  
  40.           
  41. }  
  42. //封装的业务类  
  43. class Business{  
  44.         private int data=0//共享资源属性  
  45.         private int readThreads = 0//读线程数  
  46.         //private boolean isWriting  = false;   
  47.         //是否执行写 后来发现不需要 当write抢占锁时 所有的read 都被挡在synchronized (this){}之上 无机会执行wait  
  48.         public void read(){  
  49.                 synchronized (this) {          
  50.                         /*while(isWriting){  
  51.                                 try {                          
  52.                                         this.wait();                                          
  53.                                 } catch (InterruptedException e) {  
  54.                                         // TODO Auto-generated catch block  
  55.                                         e.printStackTrace();  
  56.                                 }  
  57.                         }*/ 
  58.                         //readThreads不被锁的话 会出现read和write不互斥的小概率事件 导致线程不安全  
  59.                         readThreads++;  
  60.                           
  61.                 }  
  62.                   
  63.                 System.out.println(Thread.currentThread().getName()+" read begin");  
  64.                 System.out.println(Thread.currentThread().getName()+" read:"+data);  
  65.                 System.out.println(Thread.currentThread().getName()+" read finish");  
  66.                           
  67.                 synchronized (this) {  
  68.                         readThreads--;  
  69.                         this.notifyAll();  
  70.                 }          
  71.         }  
  72.           
  73.         public synchronized void write(int i){  
  74.                 while(readThreads != 0){//当read 正处于do something状态时 来个write 那就只有等等先了  
  75.                         try {  
  76.                                 this.wait();  
  77.                         } catch (InterruptedException e) {  
  78.                                 e.printStackTrace();  
  79.                         }  
  80.                 }  
  81.                 //isWriting = true;  
  82.                 System.out.println(Thread.currentThread().getName()+" write start");  
  83.                 data = i;  
  84.                 System.out.println(Thread.currentThread().getName()+" write:"+i);  
  85.                 System.out.println(Thread.currentThread().getName()+" write over");  
  86.                 //isWriting = false;  
  87.                 this.notifyAll();  
  88.         }  

思考中:

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

原文链接:http://www.cnblogs.com/hottea4Goodspeed/archive/2012/03/06/2381257.html

【编辑推荐】

  1. 6个提高Java开发者效率的工具
  2. Java并发:juc Executor框架详解
  3. 设计Java应用程序的平滑停止
  4. Spock 0.6发布 Java测试框架
  5. 深入Java探索:Java内存区域
责任编辑:林师授 来源: Goodspeed85的博客
相关推荐

2024-01-29 01:08:01

悲观锁递归锁读写锁

2023-01-04 13:43:24

读写锁AQS共享模式

2011-04-13 14:04:14

Java数组

2015-11-03 09:24:12

Java读写锁分析

2020-09-16 10:47:26

数字化转型企业领导者CIO

2019-11-28 16:00:06

重入锁读写锁乐观锁

2009-11-28 20:24:13

Linux互斥锁同步移植

2023-03-10 15:45:03

Golang公平锁

2024-08-12 17:36:54

2011-08-30 09:59:47

Mysql ProxyLUA

2020-05-12 14:03:51

RedisZooKeeper分布式锁

2011-06-03 13:03:03

JAVA

2024-05-15 09:41:22

乐观锁编程

2021-12-08 10:54:09

汽车智能芯片

2022-08-01 07:38:29

代码开发

2024-05-08 10:20:00

Redis分布式

2024-10-10 09:40:29

2010-06-07 15:12:12

Cacti配置

2010-05-31 14:47:28

Cacti配置

2012-11-08 11:19:38

点赞
收藏

51CTO技术栈公众号