1. Introduction to ReadWriteLock
Why do we have to use ReadWriteLock when we have Lock? After we lock the shared resource, all threads will wait. Lock read operations are also locked, and write operations are also locked. When reading shared resources, there is actually no need to lock them. Of course, there will be cases where reading and writing exist at the same time.
For example, common operations in our database include adding, deleting, modifying, and checking. Adding, deleting, and modifying are all write operations. Write operations must be locked, while read operations can be shared. Not all operations require locking.
In order to further improve the reusability and granularity, write operations are exclusive, read operations are shared, and no locks are added.
ReadWriteLock manages a set of locks, one is a read-only lock and the other is a write lock. Read locks can be held by multiple threads at the same time without write locks, and write locks are exclusive.
That is, reading and reading can be shared, and writing, reading and writing should be exclusive
Read operations do not need to care about resource contention and data consistency operations
There is no problem with multiple threads reading a resource class at the same time, so in order to meet the concurrency, reading shared resources should be possible at the same time.
But if one thread wants to write to a shared resource, no other thread should be able to read or write to that resource.
Small summary:
Read-read can coexist
Read-write cannot coexist
Write-write cannot coexist
ReadWriteLock is suitable for concurrent situations with more reads and fewer writes.
ReadWriteLock in the Java concurrent package is an interface with two main methods, as follows:
public interface ReadWriteLock {
/**
* return read lock
*/
Lock readLock();
/**
* return write lock
*/
Lock writeLock();
}
ReetrantReadWriteLock in the Java Concurrency Library implements the ReadWriteLock interface and adds reentrant features.
2. The case of not using read-write lock
class MyCache{
//volalite guarantees the visibility and certain order of data between threads
private volatile Map map=new HashMap();
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()+”\t — write data”+key);
map.put(key,value);
try {TimeUnit. SECONDS. sleep(3);} catch (InterruptedException e) {e. printStackTrace();}
System.out.println(Thread.currentThread().getName()+”\t —write completed”);
}
public void get(String key){
System.out.println(Thread.currentThread().getName()+”\t read data”);
Object result=map.get(key);
System.out.println(Thread.currentThread().getName()+”\t read completed”+result);
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyCache myCache=new MyCache();
for(int i=1;i<=5;i++){
final int tempInt=i;
new Thread(()->{
myCache.put(tempInt+””,tempInt+””);
},String.valueOf(i)).start();
}
for(int i=1;i<=5;i++){
final int tempInt=i;
new Thread(()->{
myCache.get(tempInt+””);
},String.valueOf(i)).start();
}
}
}
There is a very serious problem in the above operation results. For example, when thread 1 is writing data, other threads are also writing and reading before thread 1 finishes writing. This violates the atomicity of transactions. And it also destroys the integrity and consistency of the data. When I am writing, other threads are not allowed to write or read at the same time. That is, when 1 is written, the latter must be satisfied, that is, 1 is written.
3. The case of using read-write lock
class MyCache{
//volalite guarantees the visibility and certain order of data between threads
private volatile Map map=new HashMap();
private ReadWriteLock readwritelock=new ReentrantReadWriteLock();
public void put(String key,Object value){
readwritelock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+”\t — write data”+key);
map.put(key,value);
try {TimeUnit. SECONDS. sleep(3);} catch (InterruptedException e) {e. printStackTrace();}
System.out.println(Thread.currentThread().getName()+”\t —write completed”);
} catch (Exception e) {
// TODO: handle exception
e. printStackTrace();
}finally{
readwritelock.writeLock().unlock();
}
}
public void get(String key){
readwritelock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+”\t read data”);
Object result=map.get(key);
System.out.println(Thread.currentThread().getName()+”\t read completed”+result);
} catch (Exception e) {
// TODO: handle exception
e. printStackTrace();
}finally{
readwritelock.readLock().unlock();
}
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyCache myCache=new MyCache();
for(int i=1;i<=5;i++){
final int tempInt=i;
new Thread(()->{
myCache.put(tempInt+””,tempInt+””);
},String.valueOf(i)).start();
}
for(int i=1;i<=5;i++){
final int tempInt=i;
new Thread(()->{
myCache.get(tempInt+””);
},String.valueOf(i)).start();
}
}
}
This is the end of this article about the ReadWriteLock read-write lock for concurrent programming in Java. For more information about the Java ReadWriteLock read-write lock, please search the previous articles of Scenario House or continue to browse the following related articles. I hope you all Please support developpaer a lot in the future!