java.util.concurrent.locks

  对于线程安全我们前面使用了synchronized关键字,对于线程的协作我们使用Object.wait()和Object.notify()。在JDK1.5中java为我们提供了Lock来实现与它们相同的功能,并且性能优于它们,在JDK1.6时,JDK对synchronized做了优化,在性能上两种方式差距不大了。

一、为什么出现lock

  synchronized修饰的代码块,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,如果没有释放则需要无限的等待下去。获取锁的线程释放锁只会有两种情况:

  1、获取锁的线程执行完了该代码块,然后线程释放对锁的占有。

  2、线程执行发生异常,此时JVM会让线程自动释放锁。

Lock与synchronized对比:

  1、Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问。

  2、synchronized不需要手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

二、java.util.concurrent.locks包中常用的类和接口。

public interface Lock {
//用来获取锁。如果锁已被其他线程获取,则进行等待。
void lock();
// 当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态
void lockInterruptibly() throws InterruptedException;
//它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false
boolean tryLock();
//与tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
//释放锁
void unlock();
Condition newCondition();
}

1、Lock与unlock
  Lock用于获取锁,但它不会主动释放锁所以需要与unlock()配合使用。一般在使用Lock时必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。

package com.jalja.base.threadTest;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest implements Runnable{
public static ReentrantLock lock=new ReentrantLock();
public static int c=0;
public void run() {
for(int i=0;i<1000;i++){
lock.lock();//获取锁
try {
System.out.println(Thread.currentThread().getName()+"获得锁");
System.out.println(Thread.currentThread().getName()+"====>"+c);
c++;
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println(Thread.currentThread().getName()+"释放锁");
lock.unlock();//释放锁
}
}
}
public static void main(String[] args) {
LockTest lt=new LockTest();
Thread thread1=new Thread(lt);
Thread thread2=new Thread(lt);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(c);
}
}

注意:同一个线程可以连续获得同一把锁,但也必须释放相同次数的锁。允许下面的写法

          lock.lock();//获取锁
lock.lock();
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"获得锁");
System.out.println(Thread.currentThread().getName()+"====>"+c);
c++;
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println(Thread.currentThread().getName()+"释放锁");
lock.unlock();//释放锁
lock.unlock();//释放锁
lock.unlock();//释放锁
}

2、获取锁等待时间tryLock(long time, TimeUnit unit)
  如果你约朋友打篮球,约定时间到了你朋友还没有出现,你等1小时后还是没到,我想你肯定会扫兴的离去。对于线程来说也应该时这样的,因为通常我们是无法判断一个线程为什么会无法获得锁,但我们可以给该线程一个获取锁的时间限制,如果到时间还没有获取到锁,则放弃获取锁。

package com.jalja.base.threadTest;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; public class TryLockTest implements Runnable{
public static ReentrantLock lock=new ReentrantLock();
private static int m=0;
public void run() {
try {
if(lock.tryLock(1, TimeUnit.SECONDS)){//设置获取锁的等待时长1秒
System.out.println(Thread.currentThread().getName()+"获得锁");
m++;
//Thread.sleep(2000);//设置休眠2秒
}else{
System.out.println(Thread.currentThread().getName()+"未获得锁");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
public static void main(String[] args) {
TryLockTest thread1=new TryLockTest();
TryLockTest thread2=new TryLockTest();
Thread th1=new Thread(thread1);
Thread th2=new Thread(thread2);
th1.start();
th2.start();
try {
//让main线程等待th1、th2线程执行完毕后,再继续执行
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(m);
}
}

执行结果:

Thread-0获得锁
Thread-1获得锁
2

  该代码就是让线程在锁请求中,最多等待1秒,如果超过一秒没有获得锁就返回false,如果获得了锁就返回true,根据执行结果可以看出Thread-1线程在1秒内获得了锁。

我们开启注释 //Thread.sleep(2000);就会发现Thread-1或Thread-0一定会有一个是未获得锁,这是因为占用锁的线程时间是2秒,而等待锁的线程等待时间是1秒,所以在1秒后的瞬间它就放弃了请求锁操作。

java 线程安全 Lock的更多相关文章

  1. JAVA线程锁lock下Condition的使用

    import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...

  2. 【Java线程】Lock、Condition

    http://www.infoq.com/cn/articles/java-memory-model-5  深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...

  3. JAVA线程锁lock下Condition高级使用-多个Condition的整合使用

    import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...

  4. Java线程锁一个简单Lock

    /** * @author * * Lock 是java.util.concurrent.locks下提供的java线程锁,作用跟synchronized类似, * 单是比它更加面向对象,两个线程执行 ...

  5. Java线程新特性--- Lock

    在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks包下面,里面有三个重要的接口C ...

  6. 【Java线程】锁机制:synchronized、Lock、Condition

    http://www.infoq.com/cn/articles/java-memory-model-5  深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...

  7. Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

    (1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...

  8. 【Java线程】锁机制:synchronized、Lock、Condition(转)

    原文地址 1.synchronized 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility). 1.1 原子性 ...

  9. Java线程并发:知识点

    Java线程并发:知识点   发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用.   逃逸:在对象尚未准备 ...

随机推荐

  1. linux进程间通信-共享内存

    转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...

  2. EXCEL设置选中单元格样式

    你想这样啊,试试这段代码看行不:右键工作表名称--查看代码,在空白处粘贴就可以 Private Sub Worksheet_SelectionChange(ByVal Target As Range) ...

  3. java嵌套类

    java有四种嵌套类: 静态内部类,成员内部类,局部内部类,匿名内部类 1)静态内部类: (1)类的申明加上staitc关键字.一般用public修饰 (2)只能访问外部类的静态变量和静态方法.不能访 ...

  4. 微信小视频复制到手机本地Android APP 分享

    因为需要将拍的宝宝的微信小视频上传到亲宝宝软件,每次去手动找文件比较麻烦,所以做了个微信视频复制到手机本地的APP,做工虽然粗糙,但是绝对实用, 下载地址 http://pan.baidu.com/s ...

  5. Windows 10开机的秘密在哪里

    如何查看开机速度 查看开机速度,一定要安装所谓的第三方安全软件么?老子就是不喜欢被安全! Windows自带的事件查看器中记录了系统的一举一动,何必需要别人来监视? 在运行(WinKey+R)中输入e ...

  6. vb- ----之常用函数

    [VB]常用函数 2007-10-25 10:52 3375人阅读 评论(1) 收藏 举报 vbstringdateintegervbscriptwindows (一)类型转换类函数1. CType( ...

  7. js基础知识:表达式

    一.什么是表达式?我理解的"表达式":程序执行到1个"表达式"时,会返回1个值到这个"表达式"所在的位置. var a = 10 , b = ...

  8. 【转载】硬盘MBR详细介绍

    原文地址:http://blog.chinaunix.net/uid-15007890-id-106892.html 硬盘MBR详细介绍      硬盘是现在计算机上最常用的存储器之一.我们都知道,计 ...

  9. 去掉tableview cell的左边间隙问题

    http://www.jianshu.com/p/ba32f45222e0 简书上面的一篇文章.

  10. explode,split,preg_split性能比较

      explode,split,preg_split性能比较 分类: php2012-07-12 09:46 1109人阅读 评论(1) 收藏 举报 三个函数都是用来对字符串进行分割,下面分几个实验来 ...