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();//释放写锁
读读共享,写写互斥,读写互斥,写读互斥。

浙公网安备 33010602011771号