未加星标

Java 线程安全 Lock

字体大小 | |
[系统(linux) 所属分类 系统(linux) | 发布者 店小二05 | 时间 20160901 | 作者 红领巾 ] 0人收藏点击收藏

  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.linuxidc.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.linuxidc.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秒后的瞬间它就放弃了请求锁操作。

本文地址:http://www.codesec.net/Linux/2016-09/135341.htm


Java 线程安全 Lock

本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统

主题: JavaJVMLinux
分页:12
转载请注明
本文标题:Java 线程安全 Lock
本站链接:http://www.codesec.net/view/483470.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(linux) | 评论(0) | 阅读(22)