ReentrantLock

1.ReentrantLock概述

在java多线程中,可以使用synchronized关键字来实现线程之间同步互斥,但在JDK1.5中增加了ReentrantLock也能达到同样的效果,并且在扩展功能上也更加强大,而且使用上更加灵活。

使用ReentrantLock实现生产者消费者:

package chapter4.reentrant;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class MyStack {
	
	private List<String> list = new ArrayList<>();
	ReentrantLock lock = new ReentrantLock();
	Condition conditionp = lock.newCondition();
	Condition conditionc = lock.newCondition();
	
	public void push() {
		try {
			lock.lock();
			while(list.size() == 1) {
				System.out.println("push 操作中的:"+Thread.currentThread().getName()+" 线程呈等待状态");
				conditionp.await();
			}
			list.add("anything="+Math.random());
			conditionc.signalAll();
			System.out.println("push="+list.size());
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void pop() {
		try {
			lock.lock();
			while(list.size() == 0) {
				System.out.println("pop 操作中的:"+Thread.currentThread().getName()+" 线程呈等待状态");
				conditionc.await();
			}
			String str = list.get(0);
			System.out.println("pop "+str);
			list.remove(0);
			conditionp.signalAll();
			System.out.println("pop="+list.size());
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
}

package chapter4.reentrant;

public class P {
	private MyStack myStack;
	public P(MyStack myStack) {
		this.myStack = myStack;
	}
	
	public void pushService() {
		myStack.push();;
	}

}


package chapter4.reentrant;

public class C {
	private MyStack myStack;
	public C(MyStack myStack) {
		this.myStack = myStack;
	}
	
	public void popService() {
		myStack.pop();;
	}

}


package chapter4.reentrant;

public class ThreadP extends Thread{
	
	private P p;
	public ThreadP(P p) {
		this.p = p;
	}
	
	@Override
	public void run() {
		super.run();
		p.pushService();
	}

}


package chapter4.reentrant;

public class ThreadC extends Thread{
	
	private C c;
	public ThreadC(C c) {
		this.c = c;
	}
	
	@Override
	public void run() {
		super.run();
		c.popService();
	}

}


package chapter4.reentrant;

public class Run {
	
	public static void main(String[] args) {
		try {
			int cnt=3;
			MyStack myStack = new MyStack();
			P[] pArr = new P[cnt];
			C[] cArr = new C[cnt];
			for(int i=0;i<cnt;i++) {
				pArr[i] =new P(myStack); 
				cArr[i] = new C(myStack);;
			}
			ThreadP[] threadPs = new ThreadP[cnt];
			ThreadC[] threadCs = new ThreadC[cnt];
			for(int i=0;i<cnt;i++) {
				threadPs[i] = new ThreadP(pArr[i]);
				threadCs[i] = new ThreadC(cArr[i]);
			}
			for(int i=0;i<cnt;i++) {
				threadCs[i].start();
			}
			Thread.sleep(1000);
			for(int i=0;i<cnt;i++) {
				threadPs[i].start();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}

}

 运行结果:

pop 操作中的:Thread-1 线程呈等待状态
pop 操作中的:Thread-3 线程呈等待状态
pop 操作中的:Thread-5 线程呈等待状态
push=1
push 操作中的:Thread-2 线程呈等待状态
push 操作中的:Thread-4 线程呈等待状态
pop anything=0.04358985658650283
pop=0
pop 操作中的:Thread-3 线程呈等待状态
pop 操作中的:Thread-5 线程呈等待状态
push=1
push 操作中的:Thread-4 线程呈等待状态
pop anything=0.8139775455313625
pop=0
pop 操作中的:Thread-5 线程呈等待状态
push=1
pop anything=0.8443402579212704
pop=0

2.ReentrantLock方法介绍

  •  int getQueueLength():返回正等待获取此锁定的线程估计数。
package chapter4.reentrantmethod;

import java.util.concurrent.locks.ReentrantLock;

public class Service {
	
	public ReentrantLock lock = new ReentrantLock();
	public void method() {
		try {
			lock.lock();
			System.out.println("ThreadName:"+Thread.currentThread().getName()+"进入方法!");
			Thread.sleep(Integer.MAX_VALUE);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}

}

package chapter4.reentrantmethod;

public class Run {
	
	public static void main(String[] args) {
		try {
			final Service service = new Service();
			Runnable runnable = new Runnable() {
				public void run() {
					service.method();
				}
			};
			Thread[] threads = new Thread[10];
			for(int i=0;i<10;i++) {
				threads[i] = new Thread(runnable);
			}
			for(int i=0;i<10;i++) {
				threads[i].start();
			}
			Thread.sleep(2000);
			System.out.println(service.lock.getQueueLength()+"个线程在等待获取锁");
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}

}

 运行结果:

ThreadName:Thread-0进入方法!
9个线程在等待获取锁

  • int getHoldCount():查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
package chapter4.reentrantmethod;

import java.util.concurrent.locks.ReentrantLock;

public class Service {
	
	public ReentrantLock lock = new ReentrantLock();
	public void method1() {
		try {
			lock.lock();
			System.out.println("method1 getHoldCount:"+lock.getHoldCount());
			method2();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void method2() {
		try {
			lock.lock();
			System.out.println("method2 getHoldCount:"+lock.getHoldCount());
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}

}

package chapter4.reentrantmethod;

public class Run {
	
	public static void main(String[] args) {
		Service service = new Service();
		service.method1();
	}

}

 运行结果:

method1 getHoldCount:1
method2 getHoldCount:2

  • boolean hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的Condition条件。
  • int getWaitQueueLength(Condition condition):返回等待与此锁定条件相关的给定条件Condition的线程估计数。
package chapter4.reentrantmethod;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Service {
	
	private ReentrantLock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	public void waitMethod() {
		try {
			lock.lock();
			condition.await();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	
	public void notifyMethod() {
		try {
			lock.lock();
              System.out.println("是否有线程正在等待condition:"+lock.hasWaiters(condition)); System.out.println(lock.getWaitQueueLength(condition)+"个线程正在等待condition"); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrantmethod; public class Run { public static void main(String[] args) { try { final Service service = new Service(); Runnable runnable = new Runnable() { public void run() { service.waitMethod(); } }; Thread[] threads = new Thread[10]; for(int i=0;i<10;i++) { threads[i] = new Thread(runnable); } for(int i=0;i<10;i++) { threads[i].start(); } Thread.sleep(2000); service.notifyMethod(); } catch (Exception e) { e.printStackTrace(); } } }

 运行结果:

是否有线程正在等待condition:true
10个线程正在等待condition

  •  boolean hasQueuedThread(Thread thread):查询指定的线程是否正在等待获取此锁定。
  • boolean hasQueuedThreads():查询是否有线程正在等待获取此锁定。
package chapter4.reentrantmethod;

import java.util.concurrent.locks.ReentrantLock;

public class Service2 {
	
	public ReentrantLock lock = new ReentrantLock();
	public void waitMethod() {
		try {
			lock.lock();
			Thread.sleep(Integer.MAX_VALUE);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}

}

package chapter4.reentrantmethod;

public class Run2 {
	
	public static void main(String[] args) {
		try {
			final Service2 service = new Service2();
			Runnable runnable = new Runnable() {
				public void run() {
					service.waitMethod();
				}
			};
			Thread threada = new Thread(runnable);
			threada.start();
			Thread.sleep(500);
			
			Thread threadb = new Thread(runnable);
			threadb.start();
			Thread.sleep(500);
			System.out.println(service.lock.hasQueuedThread(threada));
			System.out.println(service.lock.hasQueuedThread(threadb));
			System.out.println(service.lock.hasQueuedThreads());
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}

}

 执行结果:

false
true
true

  • boolean isFair():判断是不是公平锁,ReentrantLock类默认使用的是非公平锁。
  • boolean isHeldByCurrentThread():查询当前线程是否保持此锁定。
  • boolean isLocked():此锁定是否由任意线程保持。
  • void lockInterruptibly():如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
  • boolean tryLock():仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。
  • boolean tryLock(long timeout, TimeUnit unit):如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。
  • void awaitUninterruptibly():线程被中断,不会抛出异常。
  • boolean awaitUntil(Date deadline):wait到某一个时间点,可以被提前唤醒。

3.ReentrantReadWriteLock

  • readLock().lock();//获取读锁
  • readLock().unlock();//释放读锁
  • writeLock().lock();//获取写锁
  • writeLock().unlock();//释放写锁

读读共享,写写互斥,读写互斥,写读互斥。

posted @ 2019-06-26 15:50  断了线的风筝~  阅读(143)  评论(0编辑  收藏  举报