Java并发程序设计(13)并发锁之读写锁

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同时成功持有读锁。

时间: 2024-10-12 22:18:14

Java并发程序设计(13)并发锁之读写锁的相关文章

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

转发 :java线程:互斥锁与读写锁

原文链接:http://coolxing.iteye.com/blog/1236909 两种互斥锁机制: 1.synchronized 2.ReentrantLock ReentrantLock是jdk5的新特性,采用ReentrantLock可以完全替代替换synchronized传统的锁机制,而且采用ReentrantLock的方式更加面向对象,也更加灵活,网上有很多关于对比两者锁方式的文章,这里就不多口舌了,大家baidu.google一下就水落石出了.在本博客中也写关于这两种锁方式实现的

内部锁、显示锁和读写锁

线程同步机制 线程同步机制是一套用于协调线程间的数据访问及活动的机制.该机制用于保障线程安全及实现这些线程的共同目标. java平台提供的线程同步机制: 锁 volatile关键字 final关键字 static关键字 其他(如:Object.wait()/Object.notify()等) 锁机制 锁机制 :将多线程并发访问共享数据转换为串行访问,一个共享数据每次只能被一个线程访问(获得锁),该线程访问结束后(释放锁)其他线程才能对其访问. 锁的获得 : 一个线程在访问数据前必须申请相应的锁.

Go36-26-互斥锁与读写锁

从同步讲起 相比于Go语言宣扬的"用通讯的方式共享数据",通过共享数据的方式来传递信息和协调线程运行的做法其实更加主流.本篇就是讨论一些与多线程.共享资源以及同步有关的知识. sync包,就是一个与并发编程关系紧密的代码包.这里"sync"的中文意思就是"同步". 重要的并发编程概念 这里会讲一些重要的并发编程概念:竞态条件.临界区.互斥量.死锁.死锁会在互斥锁里引出. 一旦数据被多个线程共享,那么就很可能会产生争用和冲突的情况.这种情况也被称为

C# lock 语法糖实现原理--《.NET Core 底层入门》之自旋锁,互斥锁,混合锁,读写锁

原文:C# lock 语法糖实现原理--<.NET Core 底层入门>之自旋锁,互斥锁,混合锁,读写锁 在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连串操作 原子操作 修改状态要么成功且状态改变,要么失败且状态不变,并且外部只能观察到修改前或者修改后的状态,修改中途的状态不能被观察到 .NET 中,System.Threading.Inte

Java并发程序设计(15)并发锁之读写锁(续二)写锁降级

1.1.1. 读写锁应用之三写锁降级 ReentrantReadWriteLock还具有写锁降级的特点,而这跟可重入性有一些关系. (1)持有写锁时可以降级为读锁. (2)持有读锁时不能升级为写锁. ReentrantReadWriteLock和ReentrantLock相似的是都有一个特点,就是可重入.可重入指已经获取到锁的线程可以再次获取锁,保证lock和unlock的次数相同即可. package com.test.concurrence; import java.util.Random;

Java并发编程之重入锁与读写锁

重入锁 重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁.重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞,该特性的实现需要解决以下两个问题. 1.线程再次获取锁.锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取. 2.锁的最终释放.线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁.锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放

java并发锁ReentrantReadWriteLock读写锁源码分析

1.ReentrantReadWriterLock基础 所谓读写锁,是对访问资源共享锁和排斥锁,一般的重入性语义为 如果对资源加了写锁,其他线程无法再获得写锁与读锁,但是持有写锁的线程,可以对资源加读锁(锁降级):如果一个线程对资源加了读锁,其他线程可以继续加读锁. java.util.concurrent.locks中关于多写锁的接口:ReadWriteLock public interface ReadWriteLock { /** * Returns the lock used for r

Java实现锁、公平锁、读写锁、信号量、阻塞队列、线程池等常用并发工具

锁的实现 锁的实现其实很简单,主要使用Java中synchronized关键字. public class Lock { private volatile boolean isLocked = false; private Thread lockingThread = null; public synchronized void lock() throws InterruptedExpection { while(isLocked){ wait(); } isLocked = true; loc