在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接口简介的更多相关文章

  1. java多线程Lock接口简介使用与synchronized对比 多线程下篇(三)

    前面的介绍中,对于显式锁的概念进行了简单介绍 显式锁的概念,是基于JDK层面的实现,是接口,通过这个接口可以实现同步访问 而不同于synchronized关键字,他是Java的内置特性,是基于JVM的 ...

  2. Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)

    1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...

  3. SQLite3 C/C++ 开发接口简介

    SQLite3 C/C++ 开发接口简介 1.0 总览 SQLite3是SQLite一个全新的版本,它虽然是在SQLite 2.8.13的代码基础之上开发的,但是使用了和之前的版本不兼容的数据库格式和 ...

  4. 显式锁(二)Lock接口与显示锁介绍

    一.显式锁简介    显式锁,这个叫法是相对于隐式锁synchronized而言的,加锁和解锁都要用户显式地控制.显示锁Lock是在Java5中添加到jdk的,同synchronized一样,这也是一 ...

  5. synchronized关键字,Lock接口以及可重入锁ReentrantLock

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  6. 线程同步 Lock接口

    同步:★★★★★ 好处:解决了线程安全问题. 弊端:相对降低性能,因为判断锁需要消耗资源,产生了死锁. 定义同步是有前提的: 1,必须要有两个或者两个以上的线程,才需要同步. 2,多个线程必须保证使用 ...

  7. Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock

    在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...

  8. jdk1.5多线程Lock接口及Condition接口

    jdk1.5多线程的实现的方式: jdk1.5之前对锁的操作是隐式的 synchronized(对象) //获取锁 { } //释放锁 jdk1.5锁的操作是显示的:在包java.util.concu ...

  9. Linux中的IO复用接口简介(文件监视?)

    I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...

随机推荐

  1. Python学习笔记(十八)@property

    # 请利用@property给一个Screen对象加上width和height属性, # 以及一个只读属性resolution: # -*- coding: utf-8 -*- class Scree ...

  2. unZip/Zip的安装

    1.apt-get安装: apt-get install zip 2.yum安装: yum install -y unzip zip

  3. Jdbc练习

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...

  4. 【BZOJ】1468: Tree(POJ1741) 点分治

    [题意]给定带边权树,求两点距离<=k的点对数.n<=40000. [算法]点分治 [题解]对于一个区域,选择其重心x作为根,则划分出来的每棵子树都是子区域,可以证明至多划分log n次( ...

  5. 【洛谷 P3199】 [HNOI2009]最小圈(分数规划,Spfa)

    题目链接 一开始不理解为什么不能直接用\(Tarjan\)跑出换直接求出最小值,然后想到了"简单环",恍然大悟. 二分答案,把所有边都减去\(mid\),判是否存在负环,存在就\( ...

  6. 2017ACM暑期多校联合训练 - Team 8 1011 HDU 6143 Killer Names (容斥+排列组合,dp+整数快速幂)

    题目链接 Problem Description Galen Marek, codenamed Starkiller, was a male Human apprentice of the Sith ...

  7. python 天气爬虫

    python3 爬取全国天气信息 制作一个天气查询软件,能够查询全国范围内的天气数据. github:https://github.com/1052687889/weatherApp 基于PyQt5编 ...

  8. Tinyos 第三版Make系统

    1.make系统安装 cd tools ./Bootstrap ./configure make sudo make install 2.make系统结构 3.第三版Makerules文件部分解析 # ...

  9. Tslib触摸屏官网【转】

    转自:https://github.com/kergoth/tslib C library for filtering touchscreen events tslib consists of the ...

  10. utsrelease.h 包含svn信息

    utsrelease.h是一个自动生成的文件,没有办法修改,但这个数据是根据Makefile和.config的内容进行生成的,通过修改这两个文件的内容,可以改变!/usr/src/linux/Make ...