java 线程安全 Lock
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的更多相关文章
- JAVA线程锁lock下Condition的使用
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...
- 【Java线程】Lock、Condition
http://www.infoq.com/cn/articles/java-memory-model-5 深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...
- JAVA线程锁lock下Condition高级使用-多个Condition的整合使用
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...
- Java线程锁一个简单Lock
/** * @author * * Lock 是java.util.concurrent.locks下提供的java线程锁,作用跟synchronized类似, * 单是比它更加面向对象,两个线程执行 ...
- Java线程新特性--- Lock
在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks包下面,里面有三个重要的接口C ...
- 【Java线程】锁机制:synchronized、Lock、Condition
http://www.infoq.com/cn/articles/java-memory-model-5 深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
(1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...
- 【Java线程】锁机制:synchronized、Lock、Condition(转)
原文地址 1.synchronized 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility). 1.1 原子性 ...
- Java线程并发:知识点
Java线程并发:知识点 发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用. 逃逸:在对象尚未准备 ...
随机推荐
- 一些不起眼但非常有用的 Vim 命令
保存文件并退出 说起来有些惭愧,我也是最近才学到这个命令
- sass基本用法(转载)
SASS入门教程及用法指南 2014年8月27日 8489次浏览 作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家都知道,js中可以自定义变量,css仅仅是一个标记语言,不是 ...
- eclipse/myeclipse sublime 实时更新文件改变
情形: 在使用eclipse/myeclipse开发的时候, 像JS 或者HTML 以及一些操作时,sublime 的效率比eclipse/myeclipse要快,所以我们就可以使用这两者一起开发. ...
- 转载扩展Windows Mobile模拟器存储空间的方法
扩展Windows Mobile模拟器存储空间的方法 在Windows Mobile应用程序开发的初期,可以使用SDK自带的模拟器来进行调试,这给我们开发人员提供了一种方便的途径.一般的应用程序,占用 ...
- 学习django之python中os模块的函数
os.sep可以取代操作系统特定的路径分隔符.windows下为 “\\” os.name字符串指示你正在使用的平台.比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'pos ...
- MySQL数据导出
1,打开命令行窗口“运行”-->输入CMD 2,进入自己MySQL Server安装目录的bin目录(我的安装目录如下) cd C:\Program Files\MySQL\MySQL Serv ...
- java.lang.RuntimeException: Method setUp in android.test.ApplicationTestCase not mocked. See http://g.co/androidstudio/not-mocked for details.
解决: build.gradle里加入: android { testOptions { unitTests.returnDefaultValues = true } }
- java中String的一些方法
1.public String(char[] c,begin,length). 从字符数组c的下标begin处开始,将长度为length的字符数组转换为字符串. begin与length可以省略,即将 ...
- SCI Index
Nature.[link] Science.[link] ...
- 自己搭建云存储(WIFI路由器上接硬盘)
欢迎转载opendevkit文章, 文章原始地址: http://www.opendevkit.com/?e=49 http://www.cnet.com/how-to/share-an-extern ...