Lock 锁与 ReentrantReadWriteLock 锁

一. Lock

Lock 锁与 synchronized 的区别

  1. 两种锁都是重入锁
  2. synchronized在代码执行完毕,或抛出异常时会自动释放锁,Lock锁在代码执行完毕或抛出异常不会自动释放锁,需要手动调用unlock()方法手动释放锁
  3. Lock 可以调用tryLocak() 方法去尝试获取锁,如果返回true则说明获取到了锁,如果返回false则说明当前不能获取锁

Lock 常用方法与使用示例

在这里插入图片描述

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
    //创建Lock对象锁,(ReentrantLock是Lock接口的实现)
    private Lock lock = new ReentrantLock();
    public static void main(String[] args) {
        //使用final修饰,是因为匿名内部类中不允许有变量
        final LockTest lockTest = new LockTest();
        //线程1
        /*匿名内部类方式创建子线程,并给子线程命名*/
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                lockTest.method(Thread.currentThread());
            }
        }, "t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                lockTest.method(Thread.currentThread());
            }
        }, "t2");
        t1.start();
        t2.start();
    }
    //需要参与同步的方法
    private void method(Thread thread) {
    /*示例1,lock()方法获取锁
    //获取锁,如果获取不到,则一直等待
    lock.lock();
        try {
            System.out.println("线程名"+thread.getName() + "获得了锁");
        }catch(Exception e){
            e.printStackTrace();
        } finally {
            System.out.println("线程名"+thread.getName() + "释放了锁");
            //由于Lock方式获取到的锁需要手动释放,需要使用try--catch在finally
            //中手动释放锁,防止代码报错时,代码无法正常执行,锁无法释放
            lock.unlock();
        }*/
        //tryLock(),获取锁,如果获取到锁,返回boolean值true否则为false
        //可以根据是否获取到锁进行指定操作
        //相同还设有tryLock(long timeout,TimeUnit unit)方法,如果获取到了锁返回true
        //如果没有获取到锁会等待指定时间unit,如果这个时间内还是获取不到锁返回false
        /*示例2,tryLock()方法获取锁, 此方法的执行最终都在finally中释放了锁*/
        if (lock.tryLock()) {
            try {
                System.out.println("线程名" + thread.getName() + "获得了锁");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("线程名" + thread.getName() + "释放了锁");
                lock.unlock();//释放锁
            }
        } else {
            System.out.println("我是" + Thread.currentThread().getName() + "有人占着锁");
        }
    }
}

二. ReentrantReadWriteLock

ReentrantReadWriteLock 可以看为读读共享,读写,写读排它,当线程执行被ReentrantReadWriteLock 修饰的代码时,首先获取的是读锁,当有读操作改为写操作时会升级为写锁,当其他线程如果要做写的操作时当前线程也会升级为写锁,读锁时允许其他线程执行做读的操作,写锁时则不允许

/*如果有一个线程已经占用了读锁,则此时其他线程
  如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
  如果有一个线程已经占用了写锁,则此时其他线程如果申请
  写锁或者读锁,则申请的线程会一直等待释放写锁*/
public class Test {
    //创建读取锁对象(当同步时,如果如果读取操作线程也会等待,影响效率,解决
    //这个问题使用读取锁)
    private u rwl = new ReentrantReadWriteLock();
    public static void main(String[] args)  {
        final Test test = new Test();
         //匿名内部类方式创建线程类并运行
        //线程类的run方法找那个调用test类的get方法
        new Thread(){
            public void run() {
                test.get(Thread.currentThread());
            };
        }.start();
        new Thread(){
            public void run() {
                test.get(Thread.currentThread());
            };
        }.start();
    }
    public void get(Thread thread) {
        //获取读取锁
        rwl.readLock().lock();
        try {
            long start = System.currentTimeMillis();
             
            while(System.currentTimeMillis() - start <= 1) {
                System.out.println(thread.getName()+"正在进行读操作");
            }
            System.out.println(thread.getName()+"读操作完毕");
        } finally {
            //释放读取锁
            rwl.readLock().unlock();
        }
    }
}

发布了48 篇原创文章 · 获赞 0 · 访问量 570

猜你喜欢

转载自blog.csdn.net/qq_29799655/article/details/105551672