1.1.1. 读写锁的应用之一读写分离
读写锁ReentrantReadWriteLock相对于ReentrantLock在特定情况下能提高同步性能,这是因为读写锁有以下特点:
(1)读和读可以同时进行。 这一点是ReentrantLock所没有的优点。
(2)读和写不能同时进行。
(3)写和写不能同时进行。
应用读写锁访问资源的代码如下所示。
class MySharedResource { private ReadWriteLock lock = new ReentrantReadWriteLock(); public void read(int taskid){ lock.readLock().lock(); try{ for(int i=0;i<10;i++){ x--; System.out.println(taskid + "," + i + ": read called: x:" + x + " , "+ Thread.currentThread().getName()); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.readLock().unlock(); } } public void write(int taskid){ lock.writeLock().lock(); try{ for(int i=0;i<10;i++){ x++; System.out.println(taskid + "," + i + ": write called: x:" + x + " , "+ Thread.currentThread().getName()); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.writeLock().unlock(); } } private int x = 0; } 创建了一个线程池来提交5个读任务和5个写任务。 final MySharedResource sr = new MySharedResource(); ExecutorService executorService = Executors.newCachedThreadPool(); int i; for( i=0;i<10;i++) { final int taskid = i; executorService.execute(new Runnable(){ @Override public void run() { System.out.println("taskid:" + taskid); if( 0 == (taskid % 2)){ sr.write(taskid); } else { sr.read(taskid); } } }); } executorService.shutdown();
一个可能的测试结果如下:
taskid:0
taskid:2
taskid:1
taskid:3
taskid:4
taskid:5
0,0: write called: x:1 , pool-1-thread-1
taskid:6
taskid:8
taskid:7
taskid:9
0,1: write called: x:2 , pool-1-thread-1
0,2: write called: x:3 , pool-1-thread-1
0,3: write called: x:4 , pool-1-thread-1
0,4: write called: x:5 , pool-1-thread-1
0,5: write called: x:6 , pool-1-thread-1
0,6: write called: x:7 , pool-1-thread-1
0,7: write called: x:8 , pool-1-thread-1
0,8: write called: x:9 , pool-1-thread-1
0,9: write called: x:10 , pool-1-thread-1
2,0: write called: x:11 , pool-1-thread-3
2,1: write called: x:12 , pool-1-thread-3
2,2: write called: x:13 , pool-1-thread-3
2,3: write called: x:14 , pool-1-thread-3
2,4: write called: x:15 , pool-1-thread-3
2,5: write called: x:16 , pool-1-thread-3
2,6: write called: x:17 , pool-1-thread-3
2,7: write called: x:18 , pool-1-thread-3
2,8: write called: x:19 , pool-1-thread-3
2,9: write called: x:20 , pool-1-thread-3
1,0: read called: x:19 , pool-1-thread-2
3,0: read called: x:18 , pool-1-thread-4
3,1: read called: x:16 , pool-1-thread-4
1,1: read called: x:16 , pool-1-thread-2
1,2: read called: x:15 , pool-1-thread-2
3,2: read called: x:14 , pool-1-thread-4
1,3: read called: x:12 , pool-1-thread-2
3,3: read called: x:12 , pool-1-thread-4
1,4: read called: x:11 , pool-1-thread-2
3,4: read called: x:10 , pool-1-thread-4
1,5: read called: x:9 , pool-1-thread-2
3,5: read called: x:9 , pool-1-thread-4
3,6: read called: x:8 , pool-1-thread-4
1,6: read called: x:7 , pool-1-thread-2
3,7: read called: x:6 , pool-1-thread-4
1,7: read called: x:6 , pool-1-thread-2
1,8: read called: x:5 , pool-1-thread-2
3,8: read called: x:4 , pool-1-thread-4
1,9: read called: x:3 , pool-1-thread-2
3,9: read called: x:3 , pool-1-thread-4
4,0: write called: x:4 , pool-1-thread-5
4,1: write called: x:5 , pool-1-thread-5
4,2: write called: x:6 , pool-1-thread-5
4,3: write called: x:7 , pool-1-thread-5
4,4: write called: x:8 , pool-1-thread-5
4,5: write called: x:9 , pool-1-thread-5
4,6: write called: x:10 , pool-1-thread-5
4,7: write called: x:11 , pool-1-thread-5
4,8: write called: x:12 , pool-1-thread-5
4,9: write called: x:13 , pool-1-thread-5
5,0: read called: x:12 , pool-1-thread-6
5,1: read called: x:11 , pool-1-thread-6
5,2: read called: x:10 , pool-1-thread-6
5,3: read called: x:9 , pool-1-thread-6
5,4: read called: x:8 , pool-1-thread-6
5,5: read called: x:7 , pool-1-thread-6
5,6: read called: x:6 , pool-1-thread-6
5,7: read called: x:5 , pool-1-thread-6
5,8: read called: x:4 , pool-1-thread-6
5,9: read called: x:3 , pool-1-thread-6
6,0: write called: x:4 , pool-1-thread-7
6,1: write called: x:5 , pool-1-thread-7
6,2: write called: x:6 , pool-1-thread-7
6,3: write called: x:7 , pool-1-thread-7
6,4: write called: x:8 , pool-1-thread-7
6,5: write called: x:9 , pool-1-thread-7
6,6: write called: x:10 , pool-1-thread-7
6,7: write called: x:11 , pool-1-thread-7
6,8: write called: x:12 , pool-1-thread-7
6,9: write called: x:13 , pool-1-thread-7
8,0: write called: x:14 , pool-1-thread-9
8,1: write called: x:15 , pool-1-thread-9
8,2: write called: x:16 , pool-1-thread-9
8,3: write called: x:17 , pool-1-thread-9
8,4: write called: x:18 , pool-1-thread-9
8,5: write called: x:19 , pool-1-thread-9
8,6: write called: x:20 , pool-1-thread-9
8,7: write called: x:21 , pool-1-thread-9
8,8: write called: x:22 , pool-1-thread-9
8,9: write called: x:23 , pool-1-thread-9
7,0: read called: x:22 , pool-1-thread-8
9,0: read called: x:21 , pool-1-thread-10
7,1: read called: x:20 , pool-1-thread-8
9,1: read called: x:20 , pool-1-thread-10
9,2: read called: x:19 , pool-1-thread-10
7,2: read called: x:19 , pool-1-thread-8
9,3: read called: x:17 , pool-1-thread-10
7,3: read called: x:17 , pool-1-thread-8
7,4: read called: x:16 , pool-1-thread-8
9,4: read called: x:16 , pool-1-thread-10
7,5: read called: x:14 , pool-1-thread-8
9,5: read called: x:14 , pool-1-thread-10
9,6: read called: x:13 , pool-1-thread-10
7,6: read called: x:12 , pool-1-thread-8
7,7: read called: x:10 , pool-1-thread-8
9,7: read called: x:10 , pool-1-thread-10
7,8: read called: x:9 , pool-1-thread-8
9,8: read called: x:9 , pool-1-thread-10
7,9: read called: x:7 , pool-1-thread-8
9,9: read called: x:7 , pool-1-thread-10
可以看到,当一个线程在持有写锁的时候,没有其他线程持有读锁,而存在线程8和线程10同时成功持有读锁。