lock接口中对应方法的实例

java中的锁
https://www.cnblogs.com/dolphin0520/p/3923167.html
lock接口,在使用的时候需要显式的获取和释放锁,拥有了一些特性:获取锁和释放锁的可操作性,可中断的获取及超时获取锁
lock的使用方式:
Lock lock = new ReentrantLock();
lock.lock();
try{
// 处理任务
}catch(Exception e){

}finally{
lock.unlock();
}
为什么要使用try finally代码块,因为使用lock的时候必须主动去释放锁,并且在发生异常的时候不会自动的释放锁,因此使用try finally代码块将释放锁的操作放在finally中进行,保证锁一定能够被释放,防止死锁的发生。但是不能在try代码块中获取锁,因为在try代码块中如果获取锁失败没有成功的获取锁,产生异常后也会执行unlock()释放锁,此时会产生异常,因为根本就没有加锁
lock接口中提供了synchronized中不具备的特性
1.尝试非阻塞的获取锁:当前线程尝试获取锁,如果这一时刻没有被其他线程获取到,则成功获取并持有锁
2.能中断的获取锁:获取到锁的线程能够响应中断,当获取到锁的线程被中断的时候,中断异常将会被抛出,同时锁会被释放
3.超时获取锁,在指定的时间之前获取锁,只等待一段时间,不让等待的线程一直无限的等待下去
Lock是一个接口
public interface Lock{
void lock();
void lockInterruptibly() throws InterruptedException;
boolean trylock();
boolean tryLock(long time,TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
其中lock(),lockIInterruptiblty() tryLock() tryLock(long time, TimeUnit unit),这些方法是用来获取锁的
Lock()方法是平常使用最多的方法,用来获取锁,如果锁已经被其他线程获取就进行等待
Lock lock = new ReentrantLock();
lock.lock()
try{
}catch(){
}fiinally{
lock.unlock();
}
boolean trylock();有返回值,用来尝试获取锁,如果获取成功返回true,如果锁已经被其他线程获取获取失败,返回false,使用这个方法的时候能够立即返回,在拿不到锁的时候不会一直在等待,尝试非阻塞的获取锁
boolean trylock(Long time ,TimeUnit unit) throws InterruptedExeption;有返回值,用来尝试获取锁,如果获取成功返回true,如果锁已经被其他线程获取获取失败,返回false,使用这个方法的时候在拿不到锁的时候会等待一定时间,如果在时间期限之内还是拿不到锁,返回false,如果在时间内或者是一开始就拿到了锁,则返回false
Lock lock = new ReentrantLock();
if(lock.trylock()){
try{
// 处理任务
}catch(Exception e){
}finally{
lock.unlock();
}
}esle{
// 不能获取到锁,则直接做其他事情
}
void lockIInterruptibly() throws interruptedException当通过这个方法获取锁的时候,如果线程正在等待获取锁,则这个线程能够响应中断,即中断 线程的等待状态。就是说,两个线程同时通过lock.lockInterruptibly()方法获取某个锁的时候,假设此时线程A获取到了锁,而线程B只有在等待状态,那么对线程B调用threadB.interrupt()方法能够中断B的等待线程
由于lockInterruptibly()的声明中抛出了异常,因此lock.lockInterruptibly()必须放在try块中或者在调用lockInterruptibly()方法声明抛出InterruptedException
public void method() throws InterruptedExxception{
lock.lockInterruptibly();
try{
//执行方法
}finally{
lock.unlock();
}
}
当一个线程获取了锁之后,是不会被interrupt()方法中断的,单独调用inerrupt()方法不能中断正在运行过程的线程,只能中断等待状态的线程,因此当通过lockInterruptibly()方法获取某个锁的时候,如果不能获取到,只有在等待的情况下是可以响应中断的。如果使用synchronized修饰的时候,当一个线程处于等待某个锁的时候,是无法被中断的,只有一直等待下去
ReentrantLock,可重入锁,ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了很多方法
lock()正确使用的方法
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test{
private ArrayList arrayList=new ArrayList<>();
protected void insert(Thread thread) {
Lock lock=new ReentrantLock();
lock.lock();
try {
System.out.println(thread.getName()+“得到了锁”);
for(int i=0;i<5;i++) {
arrayList.add(i);
}
} finally {
System.out.println(thread.getName()+“释放了锁”);
lock.unlock();
}
}
public static void main(String[] args) {
final Test test=new Test();
new Thread() {
public void run() {
test.insert(Thread.currentThread());
}
}.start();
new Thread() {
public void run() {
test.insert(Thread.currentThread());
}
}.start();
}
}
结果是:
Thread-0得到了锁
Thread-1得到了锁
Thread-0释放了锁

Thread-1释放了锁
lock()方法的作用是,用来获取锁 ,如果锁被其他线程获取到了就等待,为什么出现一个锁还没释放另一个锁就获取了?因为lock变量是一个局部变量,每个线程中都有自己的工作内存,保存一份副本,所以每个线程执行lock.lock()命令得到的说不同的锁,不会发生冲突
package binfabianchen;

import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test2 {
private ArrayList arrayList=new ArrayList<>();
private Lock lock=new ReentrantLock();
public void insert(Thread thread) {
lock.lock();
try {
System.out.println(thread.getName()+“得到了线程”);
for(int i=0;i<5;i++) {
arrayList.add(i);
}
} finally {
System.out.println(thread.getName()+“释放了锁”);
lock.unlock();
}
}

public  static void main(String[] args) {
	
	Test2 test2=new Test2();
	new Thread() {
		public void run() {
			test2.insert(Thread.currentThread());
		}
	}.start();
	
	new Thread() {
		public void run() {
			test2.insert(Thread.currentThread());
		}
	}.start();
	new Thread() {
		public void run() {
			test2.insert(Thread.currentThread());
		}
	}.start();
}

}
结果:Thread-0得到了线程
Thread-0释放了锁
Thread-1得到了线程
Thread-1释放了锁
Thread-2得到了线程
Thread-2释放了锁
使用boolean tryLock()方法
import java.sql.SQLNonTransientConnectionException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TryLockDemo {
private ArrayList arrayList=new ArrayList<>();
private Lock lock=new ReentrantLock();
public void insert(Thread thread) {
if(lock.tryLock()) {
try {
System.out.println(thread.getName()+“获得了锁”);
for(int i=0;i<100;i++) {
arrayList.add(i);
System.out.print(i+" ");
}
System.out.println();
System.out.println(“计算结束”);
} finally {
System.out.println();
System.out.println(thread.getName()+“释放了锁”);
lock.unlock();
}
}else {
System.out.println();
System.out.println(thread.getName()+“获取锁失败”);
}
}
public static void main(String[] args) throws InterruptedException {
final TryLockDemo tryLockDemo=new TryLockDemo();
new Thread() {
public void run() {
tryLockDemo.insert(Thread.currentThread());
}
}.start();
new Thread() {
public void run() {
tryLockDemo.insert(Thread.currentThread());
}
}.start();
new Thread() {
public void run() {
tryLockDemo.insert(Thread.currentThread());
}
}.start();
System.out.println(tryLockDemo.arrayList.size());
}
}
结果:
Thread-0获得了锁
0 1 2 3 4
5 6 7 Thread-1获取锁失败
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
61 62 63 64 65 66
67 68 69 70 71 72 73 74 75 76 77 Thread-2获取锁失败
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
计算结束
Thread-0释放了锁
可以发现线程0先获取了锁,在执行的过程中线程1和线程2获取锁,获取失败后没有继续等待锁,而是立即返回了false执行完毕
boolean trylock();有返回值,用来尝试获取锁,如果获取成功返回true,如果锁已经被其他线程获取获取失败,返回false,使用这个方法的时候能够立即返回,在拿不到锁的时候不会一直在等待,尝试非阻塞的获取锁

使用lockInterruptibly()响应中断的使用方法:
package binfabianchen;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockInterruptiblyDemo {
private Lock lock=new ReentrantLock();
public static void main(String[] args) {
LockInterruptiblyDemo test=new LockInterruptiblyDemo();
MyThread thread1=new MyThread(test);
MyThread thread2=new MyThread(test);
thread1.start();
thread2.start();
try {
Thread.sleep(20);//上面两个线程有一个可能没有获取到锁,处在等待状态,
} catch (Exception e) {
}
thread2.interrupt();
}
public void insert(Thread thread) throws InterruptedException {
lock.lockInterruptibly();// 获取锁,没有获取到锁将进入等待状态
try {
System.out.println(thread.getName()+“得到了锁”);
long starttime=System.currentTimeMillis();
for(;? {
if(System.currentTimeMillis()-starttime>200) {
break;
}
}
} finally {
System.out.println(Thread.currentThread().getName()+“执行finally”);
lock.unlock();
System.out.println(thread.getName()+“释放了锁”);
}
}
}
class MyThread extends Thread{
private LockInterruptiblyDemo test=null;
public MyThread(LockInterruptiblyDemo test) {
this.test=test;
}
@Override
public void run() {
try {
test.insert(Thread.currentThread());
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+“被中断”);
}
}
}

结果:Thread-0得到了锁
Thread-1被中断
Thread-0执行finally
Thread-0释放了锁
发现处于等待状态的线程被中断了,
void lockIInterruptibly() throws interruptedException当通过这个方法获取锁的时候,如果线程正在等待获取锁,则这个线程能够响应中断,即中断 线程的等待状态。就是说,两个线程同时通过lock.lockInterruptibly()方法获取某个锁的时候,假设此时线程A获取到了锁,而线程B在等待状态,那么对线程B调用threadB.interrupt()方法能够中断B的等待线程
ReadWriteLock同lock一样也是一个接口,在里面只定义了两个方法
public interface ReadWriteLock{
Lock readLock();
Lock writeLock();
}
readLock()读锁,writeLock写锁,就是说将两个文件的读写操作分开,分成两个锁来分配给线程,从而使得多个线程可以同时进行读操作,ReentrantReadWriteLock实现了ReadWriteLock接口。ReentrantReadWriteLock接口中readLock()和writeLock()方法重要
当不是用ReentrantReadWriteLock进行读写操作的时候,使用synchronized进行读写操作
public class Test3 {
public synchronized void get(Thread thread) {
long start =System.currentTimeMillis();
while(System.currentTimeMillis()-start<=0.) {
System.out.println(thread.getName()+“正在进行读操作”);
}
}

public static void main(String[] args) {
	final Test3 test3=new Test3();
	new Thread() {
		public void run() {
			test3.get(Thread.currentThread());
		}
	}.start();
		new Thread() {
		public void run() {
			test3.get(Thread.currentThread());
		}
	}.start();
}	

}
计算结果:
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
Thread-1正在进行读操作
线程thread-0读完了之后Thread-1线程才开始读读线程的时候只能单独进行
使用读写锁进行并发读
package binfabianchen;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Test4 {
private ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
public void get(Thread thread) {
readWriteLock.readLock().lock();
try {
long start= System.currentTimeMillis();
while(System.currentTimeMillis()-start<20) {
System.out.println(thread.getName()+“正在进行读操作”);
}
} finally {
System.out.println(“读操作执行完毕”);
readWriteLock.readLock().unlock();
}
}
public static void main(String[] args) {
final Test4 test4=new Test4();
new Thread() {
public void run() {
test4.get(Thread.currentThread());
}
}.start();
new Thread() {
public void run() {
test4.get(Thread.currentThread());
}
}.start();
new Thread() {
public void run() {
test4.get(Thread.currentThread());
}
}.start();
}
}
结果:Thread-0正在进行读操作
Thread-0正在进行读操作
Thread-2正在进行读操作
Thread-2正在进行读操作
读操作执行完毕
Thread-0正在进行读操作
读操作执行完毕
Thread-1正在进行读操作
读操作执行完毕
使用readLock()读锁的时候可以并发的读
lock和synchronized的选择,lock是一个接口,synchronized是java中的关键字,lock接口可以对锁的获取和释放进行控制,要显式的获取和释放锁,如果没有主动释放可能造成死锁的现象,因此使用lock的时候使用finally代码块释放锁,lock中的lockInterruptibly()可以响应中断,对于正在等待锁的线程可以响应中断,而synchronized不行只能一直的等待下去,lock中的trylock和trylock可以尝试无阻塞的获取锁,当没有获取到锁的时候会返回false,lock的读写多可以提高读操作的效率

ReadWriteLock接口中包含了,ReentrantReadWriteLock实现了ReadWriteLock接口
Lock readlock(),
Lock writeLock()方法
可重入锁,如果锁有可重入性,就称为可重入锁,想是synchronized和ReentrantLock都是可重入锁,可重入性就是锁的分配特性,基于线程的分配而不是基于方法调用的分配:当一个线程执行到某个synchronzied修饰的方法的时候 ,在这个方法中调用了另一个方法,而线程不必重新申请锁,而是可以直接执行另一个synchronzed修饰的方法
public class MyClass{
public sysnchronized void method1(){
method2();
}
public synchronzied void method2(){

}

}
这两个方法都用了synchronized方法修饰,某一时刻线程A执行到了method1,此时下次线程A获取到了这个对象的锁,由于method2也是synchtonized方法,如果synchronized不具备可重入性,此时线程A要重新申请锁,就会造成一个问题,因为线程A已经持有了对象的锁,还要重新申请对象的锁,这样A就一直等待永远不会获取到锁,synchronzied和Lock都具有可重入性
可中断锁。可以相应中断的锁,在java中synchronzed就不是可中断的锁,而Lock是可中断的锁
如果一个线程A在执行锁中的代码,另一个线程B正在等待获取锁,由于等待的时间过长,线程B不想等待了,想先处理其他事情,就可以让它中断,或者在别的线程中中断它,这中就是可中断锁
公平锁,尽量以请求锁的顺序来获取锁,如果同时有多个线程在等待一个锁,当这个锁被释放的时候,等待时间最久的线程最先请求的线程会先获得锁
非公平锁,无法保证锁的获取是按照请求锁的顺序来进行的,可能导致某个或者一些线程永远获取不到锁,synchronzied就是公平锁,它无法保证等待的线程获取锁的顺序,ReentrantLock和ReentrantReadWriteLock默认情况是非公平锁,但是可以设置为公平锁ReentrantLock中定义了两个静态内部类,一个是NotFairSync,一个是FairSync分别用来实现非公平锁和公平锁,ReentrantLock lock=new ReentrantLock(true);
表示如果参数为true表示为公平锁,如果为false为非公平锁
读写锁,将对一个资源的访问分成了两个锁,一个是读锁一个是写锁,有了读写锁之后才使得多个线程之间的读操作不会发生冲突

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值