类ReentranLock具有万川互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。这样虽然保证了实例变量的线程安全性,
但效率却是非常低下的。所以在jdk中提供了一种读写锁ReentrantReadWriteLock类,使它可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁
ReentrantReadWriteLock来提升该方法的代码运行速度。
读写锁表示也有两个锁,一个是读操作相关的锁,也称为共享锁;另一个事写操作相关的做,也叫排他锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。
在没有现成Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在获取写锁后才能进行写入操作。即多个Thread可以同时进行读取操作,但是同一时刻,只允许一个Thread进行写入操作。
读读共享:
Service类:
package ReadAndWriteLock;
import java.io.BufferedWriter;
import java.time.LocalDate;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Service {
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public void read(){
try {
try {
lock.readLock().lock();;
System.out.println("线程 : "+Thread.currentThread().getName()+" 时间: "+System.currentTimeMillis()+" 获得锁");
Thread.sleep(10000);
} finally {
lock.readLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
主方法:
package ReadAndWriteLock;
public class Run {
public static void main(String[] args) {
final Service service=new Service();
new Thread(new Runnable() {
public void run() {
service.read();
}
}).start();
new Thread(new Runnable() {
public void run() {
service.read();
}
}).start();
}
}
控制台:
线程 : Thread-0 时间: 1534585340658 获得锁 线程 : Thread-1 时间: 1534585340659 获得锁
可以发现,两个线程几乎同时进入了lock方法后面的代码,说明在此使用读写锁可以提供程序运行效率,允许多个线程同时制定lock()方法后面的代码。
写写互斥:
Service类
public class Service1 {
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public void write() {
try {
try {
lock.writeLock().lock();;
System.out.println("线程: "+Thread.currentThread().getName()+" 时间: "+System.currentTimeMillis()+" 获得锁");
Thread.sleep(10000);
} finally {
lock.writeLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
主线程:
public class Run {
public static void main(String[] args) {
final Service1 service1=new Service1();
new Thread(new Runnable() {
public void run() {
service1.write();
}
}).start();
new Thread(new Runnable() {
public void run() {
service1.write();
}
}).start();
}
}
控制台:
线程: Thread-0 时间: 1534585587952 获得锁 线程: Thread-1 时间: 1534585597955 获得锁
使用写锁代码lock.writeLock()的效果就是同意时间只允许一个线程执行lock()方法后面的代码。
写读互斥:
service2类
public class Service2 {
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public void read() {
try {
try {
lock.readLock().lock();
System.out.println("线程: "+Thread.currentThread().getName()+" 时间: "+System.currentTimeMillis());
Thread.sleep(10000);
} finally {
lock.readLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("线程: "+Thread.currentThread().getName()+" 时间: "+System.currentTimeMillis());
Thread.sleep(10000);
} finally {
lock.writeLock().unlock();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
主线程:
public class Run {
public static void main(String[] args) {
final Service2 service2=new Service2();
new Thread(new Runnable() {
public void run() {
service2.write();
}
}).start();
new Thread(new Runnable() {
public void run() {
service2.read();
}
}).start();
}
}
控制台:
线程: Thread-0 时间: 1534586198910 线程: Thread-1 时间: 1534586208910
从时间上看,写读操作是互斥的。
读写互斥:
将主线程中的方法改为如下:
public class Run {
public static void main(String[] args) throws InterruptedException {
final Service2 service2=new Service2();
new Thread(new Runnable() {
public void run() {
service2.read();
}
}).start();
Thread.sleep(1000);
new Thread(new Runnable() {
public void run() {
service2.write();
}
}).start();
}
}
控制台:
线程: Thread-0 时间: 1534586426809 线程: Thread-1 时间: 1534586436810
读写操作也是互斥的。
结论: 读写,写读,写写都是互斥的:而读读是异步的,非互斥的。
每一个优秀的人,都有一段沉默的时光。不抱怨,不诉苦,最后度过那段感动自己的日子。
浙公网安备 33010602011771号