十一、多线程控制类(2)

前言:

  前面我们介绍了多线程的控制类ThreadLocal和一些原子类,下面我们来看一下其中两个比较重的关于多线程的控制类和关键字。

一、Lock类:

  如下是一张关于Lock接口的接口以及实现类的关系图,接下来就具体来看一下其中的关系:

  

  1、Lock和ReadWriteLock是两大锁的根接口,Lock代表实现类是ReentrantLock(可重入锁),ReadWriteLock(读写锁)的代表实现类是ReentrantReadWriteLock。

    Lock 接口支持那些语义不同(重入、公平等)的锁规则,可以在非阻塞式结构的上下文(包括 hand-over-hand 和锁重排算法)中使用这些规则。主要的实现是 ReentrantLock。
ReadWriteLock 接口以类似方式定义了一些读取者可以共享而写入者独占的锁。此包只提供了一个实现,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。
  2、Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。

  3、可重入锁:

    所谓的重入锁,就是线程可以进入他已经拥有锁的的代码中,不可重入锁即线程请求他已经拥有所得代码会阻塞,下面来看一个简单的重入锁案例:

public class ThreadDemo implements  Runnable {

    @Override
    public void run() {
        startDo1();
    }

    public synchronized  void startDo1(){
        System.out.println("可重入锁演示");
        startDo2();
    }

    public synchronized void startDo2(){
        System.out.println("学不会啊");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new ThreadDemo());
        thread.start();
    }
}
View Code

    上面的代码就是一个简单的重入锁案例,可以看到ThreadDemo勒种有两个同步方法,在startDo1方法中调用了startDo2方法,执行代码后可以正确的运行,也就是线程在进入startDo1方法后拿到了锁,在进入startDo2方法默认也是获取到了锁的,也就是默认第二次获取到了所对象,同时解锁的时候也需要解锁两次,这就是所谓的重入锁。

  4、读写锁:

    读写锁,即读和写是分开的,我们可以给读加锁,多个线程可以同时读,但是多个线程读的时候是不可以写的,写操作是多个线程不能同时执行写操作的,而且写的时候是不能执行读操作的。

public class ReadWriteDemo{

    private Map<String, String> map = new HashMap<String, String>();
    private ReentrantReadWriteLock  readWrite = new ReentrantReadWriteLock();
    private ReentrantReadWriteLock.ReadLock readLock = readWrite.readLock();
    private ReentrantReadWriteLock.WriteLock writeLock = readWrite.writeLock();

    public String get(String key){
        readLock.lock();
        try{
            System.out.println(Thread.currentThread().getName() + "读操作已加锁,开始读操作……");
            Thread.sleep(2000);
            return map.get(key);
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getName() +"读操作已解锁,读操作已结束……");
            readLock.unlock();
        }
        return null;
    }

    public void set(String key, String value){
        writeLock.lock();
        try{
            System.out.println(Thread.currentThread().getName() +"写操作已加锁,开始写操作");
            map.put(key,value);
            Thread.sleep(2000);
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getName() +"写操作已解锁,写操作已结束……");
            writeLock.unlock();
        }
    }
}
View Code

    测试代码:

public class ThreadDemo {

    public static void main(String[] args) {
        ReadWriteDemo  readWriteDemo = new ReadWriteDemo();
        readWriteDemo.set("key","value");
        new Thread(() -> {
            System.out.println(readWriteDemo.get("key")) ;
        }).start();
    }
}
View Code

    测试结果:

main写操作已加锁,开始写操作
main写操作已解锁,写操作已结束……
Thread-0读操作已加锁,开始读操作……
Thread-0读操作已解锁,读操作已结束……
value

Process finished with exit code 0
View Code

猜你喜欢

转载自www.cnblogs.com/zouxiangzhongyan/p/11517866.html
今日推荐