java多线程中显式锁的轮询检测策略

显式锁简介

java5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile,java5.0增加了一种新的机制:ReentrantLock。

锁像synchronized同步块一样,是一种线程同步机制,与synchronized不同的是ReentrantLock提供了一种无条件的、可轮询的、定时的以及可以中断的锁获取操作,并且所有的加锁和解锁的方法都是显式的,所以也叫显式锁。

synchronized的实现中包含了锁机制,但是锁的获取和释放不能人为的进行控制,所以当我们要定时获取锁,检测锁是否被占用时就应当使用显式锁。

显式锁涉及的类和接口

ReentrantLock实现了Lock接口,位于Java的J.U.C包中,包含了一下几个主要方法:

1、void lock(),获取锁;

2、void unlock(),释放锁;

3、boolean trylock(),仅在调用时锁为空闲状态才获取该锁;

4、boolean tryLock(long time, TimeUnit unit),如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。

显式锁的简单使用

下面我们就分别使用synchronized和lock实现小红借书的需求。

需求:小明和小红去借书,每人借10本。一个人借完之后才允许另外一个人借。

分析:

1、小明和小红相当于 2个线程;

2、借10本书视为一个操作即循环10次;

3、一个人借完之后才允许另外一个人借。

要实现必须保证借书的10次操作中间不能发生线程的切换,因此可以使用 synchronized 同步块或显示锁 ReentrantLock 来保证。

synchronized方式

cbf1500bca32d30ada11226bb6cd3390532110fa

ReentrantLock方式

d6ce85b9173bd0c899d6043cb8a606547b117825

本案例中在lock 和unlock 中间的代码块与synchronized 包裹的代码块是等效的。可以保证在执行unlock之前该线程不会让出资源给其它线程执行。

实现轮询锁

需求:小明和小红去借书,但是书只有一本,假如小明借到了,看完这本书需要5秒,

在小明读书的时间内,小红还会多次去借书,直到小明归还小红才能借到。

分析:

1、小明和小红去借书,但是书只有一本 ,从这里可以分析出需要两个线程;

2、假如小明借到了,看完这本书需要5秒,借到书可以视为获取到锁;

3、在小明读书的时间内,小红还会多次去借书,可以视为小红未获得锁,所以需要多次尝试去获得锁;

4、直到小明归还小红才能借到,可以视为小明的线程释放锁,小红获得锁。

efd0321ae9a1ab49a8ca41c3b060f6b4bd704ab2

总结

不论使用synchronized 还是使用显示锁lock都可以解决代码块同步的问题。synchronized 使用更方便,获得锁和释放锁不需要手动处理,但控制粒度不够细致。lock显式锁需要使用lock()手动加锁,unlock()手动释放锁,使用起来相对复杂,但可以实现更精细的锁控制。

使用trylock结合轮询可以实现检测锁是否空闲的效果。


原文发布时间为:2018-11-13

本文来自云栖社区合作伙伴“Java程序员联盟”,了解相关信息可以关注“Java程序员联盟”。

猜你喜欢

转载自yq.aliyun.com/articles/668817