共享锁和排他锁
- 排它锁
排它锁⼜称独占锁,获得了以后既能读⼜能写,其他没有获得锁的线程不能读也不能写,典型的synchronized就是排它锁
- 共享锁
共享锁⼜称读锁,获得了共享锁以后可以查看但⽆法修改和删除数据,其他线程也能获得共享锁,也可以查看但不能修改和删除数据
在没有读写锁之前,我们虽然保证了线程安全,但是也浪费了⼀定的资源,因为多个读操作同时进⾏并
没有线程安全问题
ReentrantReadWriteLock中 读锁就是共享锁,写锁是排它锁,在读的地⽅使⽤读锁,在写的地⽅使⽤
写锁,灵活控制,如果不这样,读是⽆限阻塞的,这样提⾼了程序的执⾏效率
1.3 读写锁的规则
多个线程只申请读锁,都能申请到如果有⼀个线程已经占⽤了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会⼀直等待释放
该锁,如果有⼀个线程已经占⽤ 写锁,则其他线程申请写锁或读锁都要等待它释放,也就是说,要么多读,要么⼀写
下⾯的示例让两个线程去读,两个线程去写,使⽤读写锁读的线程是同时进⾏的,⽽写的线程等读的线程执⾏完再依次执⾏
package org.example.c4;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class RWLock {
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//读锁
private static ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
//写锁
private static ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
private static void read() {
readLock.lock();
try {
System.out.println(Thread.currentThread().getName() + "得到了读锁,正在读取");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "释放了读 锁");
readLock.unlock();
}
}
private static void write() {
writeLock.lock();
try {
System.out.println(Thread.currentThread().getName() + "得到了写 锁,正在写⼊");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "释放了写 锁");
writeLock.unlock();
}
}
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
read();
}
}, "t1").start();
new Thread(new Runnable() {
@Override
public void run() {
read();
}
}, "t2").start();
new Thread(new Runnable() {
@Override
public void run() {
write();
}
}, "t3").start();
new Thread(new Runnable() {
@Override
public void run() {
write();
}
}, "t4").start();
}
}