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. 今天我们要说的画一个三角形,恩,画一个三角形,第一种呢是利用我们的html标签结合css来实现;而第二种方法就就是我们的html5新增的一个标签canves,这个canves就是网页画幕,那么顾名思义就是在网页里建造一个画板,用来画画,好,那接下来就和我一起去看看吧!

    第一种方法:利用我们的html标签结合css来实现 span{ width:0px; height:0px; border-width:7px; border-style:solid; border- ...

  2. iOS和Android测试区别

    1.      Android长按home键呼出应用列表和切换应用,然后右滑则终止应用: 2.      多分辨率测试,Android端20多种,ios较少: 3.      手机操作系统,Andro ...

  3. 搜索引擎 ElasticSearch 之 步步为营1 【环境搭建&初识ElasticSearch】

    1.下载ElasticSearch a.下载Java环境JDK:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloa ...

  4. 「2014-2-23」Note on Preliminary Introduction to Distributed System

    今天读了几篇分布式相关的内容,记录一下.非经典论文,非系统化阅读,非严谨思考和总结.主要的着眼点在于分布式存储:好处是,跨越单台物理机器的计算和存储能力的限制,防止单点故障(single point ...

  5. 03、AngularJs的模块与控制器

    大部分的应用程序都有一个主方法(main)来组织,实例化,启动应用程序.而AngularJs应用是没有主方法的,它是通过模块来声明应用应该如何启动的.同时,模块允许声明来描述应用中依赖关系,以及如何进 ...

  6. 【转】COM技术内幕(笔记)

    COM技术内幕(笔记) COM--到底是什么?--COM标准的要点介绍,它被设计用来解决什么问题?基本元素的定义--COM术语以及这些术语的含义.使用和处理COM对象--如何创建.使用和销毁COM对象 ...

  7. oracle sys as dba

    ====管理分区表====1.添加分区(若已设置取值范围为MAXVALUE的分区,则会报ORA-14174分区界限必须调整为高于最后一个分区界限)alter table test_part_tab a ...

  8. 升级到win8.1右键响应慢

    网上很多资料都是在显卡上做文章,试了N次确定不是这个问题. 后来查到这个好用了.以管理员身份运行 下面代码保存bat即可 regsvr32 /u /s igfxpph.dll reg delete H ...

  9. [原] XAF How can I change XafDisplayNameAttribute dynamically

    void ViewControlsCreated(object sender, EventArgs e) { foreach (StringPropertyEditor item in view.Ge ...

  10. js学习笔记之一

    一.Javascript 中的对象 1. 建立自定义对象 方法1:对象={属性1:属性值1,属性2:属性值2……属性n:属性值n} 方法2:先定义构造函数,再new创建对象实例. 如: functio ...