在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 ...
随机推荐
-
Windows Phone 如何在程序中播放提示声音?
在Windows Phone 中播放提示音可以使用 Microsoft.Xna.Framework.Audio 命名空间下的 SoundEffect 类.具体使用方法如下: 1. 根据声音文件路径创建 ...
-
android 定制自己的日志工具
最理想的情况是能够控制日志的打印,当程序处于开发阶段就让日志打印出来,当程序上线之后就把日志屏蔽掉. 例如打印一行WARN级别的日志就可以写成这样: LogUtil.w("TAG" ...
-
打开genesis时一直在等待,后出现Timeout in communication read解决方法
运行输入:netsh winsock reset 然后重启电脑
-
[51NOD1126]求递推序列的第n项(矩阵快速幂)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1126 存在参数a,b为负数的情况.这时候要这么处理: 根据mo ...
-
前端性能监控系统ShowSlow
作者:zhanhailiang 日期:2014-11-14 1. 简单介绍 ShowSlow是开源的前端性能监控系统,提供了下面功能: 前端性能指标数据收集功能:ShowSlow原生提供了数据收集工具 ...
-
Got Stucked in C++ Static Library Loading.. for some time
I used to load library using 1 single .dll file, so when I happen to do method calling between 2 pro ...
-
后端Nodejs利用node-xlsx模块读取excel
后端Nodejs(利用node-xlsx模块) /** * Created by zh on 16-9-14. */ var xlsx = require("node-xlsx") ...
-
Python开发简单爬虫(二)---爬取百度百科页面数据
一.开发爬虫的步骤 1.确定目标抓取策略: 打开目标页面,通过右键审查元素确定网页的url格式.数据格式.和网页编码形式. ①先看url的格式, F12观察一下链接的形式;② 再看目标文本信息的标签格 ...
-
Ex 5_22 在此我们基于以下性质给出一个新的最小生成树算法..._第九次作业
(a)设环的顶点集为V, e(u,v)为权最重的边,若把V分成两部分V1,V2.其中V1包含u,V2包含v,因为V是一个环,因此,至少存在两条把u和v连接起来的边.因此,除了e之外,至少还存在另一条边 ...
-
《剑指offer》第五十五题(平衡二叉树)
// 面试题55(二):平衡二叉树 // 题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树.如果某二叉树中 // 任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树. #includ ...