Lock接口简介
在Java多线程编程中,我们经常使用synchronized关键字来实现同步,控制多线程对变量的访问,来避免并发问题。
但是有的时候,synchronized关键字会显得过于沉重,不够灵活。synchronized 方法或语句的使用提供了对与每个对象相关的隐式监视器锁的访问,但却强制所有锁获取和释放均要出现在一个块结构中:当获取了多个锁时,它们必须以相反的顺序释放,且必须在与所有锁被获取时相同的词法范围内释放所有锁。
这个时候Lock出现。
Lock不是Java中的关键字而是 java.util.concurrent.locks 包中的一个接口。下面我们简单介绍一下Lock接口。
一、Lock接口简介
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。
Lock相对于synchronized关键字而言更加灵活,你可以自由得选择我你想要加锁的地方。当然更高的自由度也带来更多的责任。
我们通常会在try...catch模块中使用lock关键字,在finally模块中释放锁。下面是示范代码。
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
锁的锁定和释放如果在不同的模块时,需要谨慎编码,确保最后锁一定能够得到释放。
二、Lock接口中定义的方法
1、void lock()
获取锁。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态
2、void lockInterruptibly()
如果当前线程未被中断,则获取锁。
3、Condition newCondition()
返回绑定到此 Lock 实例的新 Condition 实例。
4、boolean tryLock()
仅在调用时锁为空闲状态才获取该锁。如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
5、boolean tryLock(long time, TimeUnit unit)
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
6、void unlock()
释放锁。在等待条件前,锁必须由当前线程保持。调用 Condition.await() 将在等待前以原子方式释放锁,并在等待返回前重新获取锁。
三、实现类ReentrantLock
Lock接口有三个实现类分别是ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock。后面两个是内部类。
第一个ReentrantLock,在我们平常使用中更为频繁。
ReentrantLock是一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
ReentrantLock的构造方法接受一个可选的公平 参数。当设置为 true 时,在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程。否则此锁将无法保证任何特定访问顺序。也就是说这里可以设置锁的类型为公平锁还是非公平锁。但是,需要注意的是公平锁的情况下,也不能完全确保公平,它总是趋向公平的情况。
ReentrantLock类中还定义了Lock接口之外的方法,例如int getHoldCount() 、boolean hasQueuedThreads() 、boolean hasWaiters(Condition condition)等等,这些方法可以查询当前锁的状态。
四、代码使用
package com.test; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class TestLock { public static void main(String[] args) {
Lock lock = new ReentrantLock();
for(int i=0;i<5;i++){
ThreadPrintStar threadPrintStar = new TestLock().new ThreadPrintStar(lock);
threadPrintStar.start();
}
} /**
* 打印星星
* @author LKB
*
*/
class ThreadPrintStar extends Thread{
private Lock lock; public ThreadPrintStar(Lock lock) {
// TODO Auto-generated constructor stub
this.lock = lock;
} public void run(){
lock.lock();
try {
for(int i=0;i<5;i++){
if(i%2 == 0)
System.out.println("i = " + i + "+++" + Thread.currentThread().getName() +
" print: " + "☆☆");
else
System.out.println("i = " + i + "+++" + Thread.currentThread().getName() +
" print: " + "★★"); }
System.out.println();
System.out.println();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
lock.unlock();
}
}
} }
下面是程序运行结果,可以看到我们通过Lock实现了同步。
i = 0+++Thread-0 print: ☆☆
i = 1+++Thread-0 print: ★★
i = 2+++Thread-0 print: ☆☆
i = 3+++Thread-0 print: ★★
i = 4+++Thread-0 print: ☆☆ i = 0+++Thread-1 print: ☆☆
i = 1+++Thread-1 print: ★★
i = 2+++Thread-1 print: ☆☆
i = 3+++Thread-1 print: ★★
i = 4+++Thread-1 print: ☆☆ i = 0+++Thread-2 print: ☆☆
i = 1+++Thread-2 print: ★★
i = 2+++Thread-2 print: ☆☆
i = 3+++Thread-2 print: ★★
i = 4+++Thread-2 print: ☆☆ i = 0+++Thread-4 print: ☆☆
i = 1+++Thread-4 print: ★★
i = 2+++Thread-4 print: ☆☆
i = 3+++Thread-4 print: ★★
i = 4+++Thread-4 print: ☆☆ i = 0+++Thread-3 print: ☆☆
i = 1+++Thread-3 print: ★★
i = 2+++Thread-3 print: ☆☆
i = 3+++Thread-3 print: ★★
i = 4+++Thread-3 print: ☆☆
Lock接口简介的更多相关文章
- java多线程Lock接口简介使用与synchronized对比 多线程下篇(三)
前面的介绍中,对于显式锁的概念进行了简单介绍 显式锁的概念,是基于JDK层面的实现,是接口,通过这个接口可以实现同步访问 而不同于synchronized关键字,他是Java的内置特性,是基于JVM的 ...
- Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)
1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...
- SQLite3 C/C++ 开发接口简介
SQLite3 C/C++ 开发接口简介 1.0 总览 SQLite3是SQLite一个全新的版本,它虽然是在SQLite 2.8.13的代码基础之上开发的,但是使用了和之前的版本不兼容的数据库格式和 ...
- 显式锁(二)Lock接口与显示锁介绍
一.显式锁简介 显式锁,这个叫法是相对于隐式锁synchronized而言的,加锁和解锁都要用户显式地控制.显示锁Lock是在Java5中添加到jdk的,同synchronized一样,这也是一 ...
- synchronized关键字,Lock接口以及可重入锁ReentrantLock
多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...
- 线程同步 Lock接口
同步:★★★★★ 好处:解决了线程安全问题. 弊端:相对降低性能,因为判断锁需要消耗资源,产生了死锁. 定义同步是有前提的: 1,必须要有两个或者两个以上的线程,才需要同步. 2,多个线程必须保证使用 ...
- Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock
在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...
- jdk1.5多线程Lock接口及Condition接口
jdk1.5多线程的实现的方式: jdk1.5之前对锁的操作是隐式的 synchronized(对象) //获取锁 { } //释放锁 jdk1.5锁的操作是显示的:在包java.util.concu ...
- Linux中的IO复用接口简介(文件监视?)
I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...
随机推荐
- HDU 2608 底数优化分块 暴力
T(n) as the sum of all numbers which are positive integers can divied n. and S(n) = T(1) + T(2) + T( ...
- 760A 水
LINK 第一天单独一行 其余7天一行 问某月有多少行 ...... /** @Date : 2017-04-02-21.35 * @Author : Lweleth (SoungEarlf@gmai ...
- c# windows server安装启动与卸载
使用installutil.exe安装卸载服务时,由于需要指向服务的全路径,由于生成目录往往不是服务发布的最终目录,很不便利,下面介绍两种方式方便操作: 方式一: 项目中加入install.bat与u ...
- JSON 为王,为什么 XML 会慢慢淡出人们的视野?
目前全球信息基础设施的特点是,拥有大量的数据交换格式.这一点也不奇怪.互联网几乎已经老了,而“物联网”及“大数据”正从概念走进现实.但我仍然相信,在这一领域还有一股较强的历史趋势,推动 JSON 数据 ...
- 35 - 并发编程-GIL-多进程
目录 1 GIL 1.1 为什么会有GIL 1.2 GIL与thread lock 1.3 个人总结 2 multiprocessing模块 2.1 Process类 2.2 Process类的方法 ...
- Linux内核同步原语之原子操作
避免对同一数据的并发访问(通常由中断.对称多处理器.内核抢占等引起)称为同步. ——题记 内核源码:Linux-2.6.38.8.tar.bz2 目标平台:ARM体系结构 原子操作确保对同一数据的“读 ...
- python近期遇到的一些面试问题(三)
python近期遇到的一些面试问题(三) 整理一下最近被问到的一些高频率的面试问题.总结一下方便日后复习巩固用,同时希望可以帮助一些朋友们. 前两期点这↓ python近期遇到的一些面试问题(一) p ...
- java-String中的 intern()
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...
- myeclipse/eclipse安装反编译插件jadclipse
jad是一个使用比较广泛的Java反编译软件,jadClipse是jad在eclipse下的插件,下面像大家介绍下如何将jadclipse加入到myeclipse/eclipse中. 文件下载 (1) ...
- oracle造成系统CPU过高的检查sql
1. 根据占用CPU高的进程号来查询这个进程执行的SQL语句: CPU过高的进程号: #首先找到CPU过高的进程号 # top -bn1 是静态找到占用最高的进程 [root@localhost ~] ...