共享锁和排他锁

  1. 排它锁

排它锁⼜称独占锁,获得了以后既能读⼜能写,其他没有获得锁的线程不能读也不能写,典型的synchronized就是排它锁

  1. 共享锁

共享锁⼜称读锁,获得了共享锁以后可以查看但⽆法修改和删除数据,其他线程也能获得共享锁,也可以查看但不能修改和删除数据

在没有读写锁之前,我们虽然保证了线程安全,但是也浪费了⼀定的资源,因为多个读操作同时进⾏并

没有线程安全问题

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();
 }
}