java并发之ReentrantLock学习理解
简介
java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路通知分支等功能,并且使用上比synchronized更加灵活。
如何使用ReentrantLock
主要是lock.lock()和lock.unlock()两个方法
public class MyService implements Runnable { protected ReentrantLock lock; public MyService(ReentrantLock lock){
this.lock = lock;
} public void run() {
lock.lock();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.unlock();
} }
/**
* 测试类
* @author ko
*
*/
public class Test { public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
for (int i = 0; i < 4; i++) {
new Thread(new MyService(lock)).start();
}
}
}
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
Thread-3 0
Thread-3 1
Thread-3 2
Thread-3 3
Thread-3 4
使用Condition类实现wait、notify的功能
Condition类也是jdk1.5里出来的,它能实现synchronized和wait、notify搭配的功能,另外比后者更灵活,Condition可以实现多路通知功能,也就是在一个Lock对象里可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择的进行线程通知,在调度线程上更加灵活。
而synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册在这个对象上。线程开始notifyAll时,需要通知所有的WAITING线程,没有选择权,会有相当大的效率问题。
使用Condition为什么会报java.lang.IllegalMonitorStateException异常
还是刚才的代码,稍作改动
public class MyService implements Runnable { protected ReentrantLock lock;
protected Condition condition; public MyService(ReentrantLock lock,Condition condition){
this.lock = lock;
this.condition = condition;
} public void run() {
// lock.lock();
try {
condition.await();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// lock.unlock();
} }
/**
* 测试类
* @author ko
*
*/
public class Test { public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
for (int i = 0; i < 4; i++) {
new Thread(new MyService(lock,condition)).start();
}
}
}
Exception in thread "Thread-0" Exception in thread "Thread-1" Exception in thread "Thread-2" Exception in thread "Thread-3" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
at ww.MyService.run(MyService.java:26)
at java.lang.Thread.run(Unknown Source)
报错的异常信息是监视器出错,原因是在调用condition.await()之前是要先调用lock.lock()来获得同步监视器。
正确使用Condition类
public class MyService implements Runnable { protected ReentrantLock lock;
protected Condition condition; public MyService(ReentrantLock lock,Condition condition){
this.lock = lock;
this.condition = condition;
} public void await(){
try {
lock.lock();
System.out.println("await time is "+System.currentTimeMillis());
condition.await();
System.out.println("after await info...");
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
} public void signal(){
try {
lock.lock();
System.out.println("signal time is "+System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
} public void run() {
await();
} }
/**
* 测试类
* @author ko
*
*/
public class Test { public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
MyService service = new MyService(lock,condition);
new Thread(service).start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
service.signal();
}
}
await time is 1501142954379
signal time is 1501142957381
after await info...
成功实现等待通知模式,整理一下,下表的方法功能是对应的
Object类 |
Condition类 |
Wait() |
Await() |
Wait(long timeout) |
Await(long time,TimeUnit unit) |
Notify() |
Signal() |
notifyAll() |
signalAll() |
使用多个Condition实现通知部分线程
public class MyService implements Runnable { protected ReentrantLock lock;
protected Condition conditionA;
protected Condition conditionB; public MyService(ReentrantLock lock,Condition conditionA,Condition conditionB){
this.lock = lock;
this.conditionA = conditionA;
this.conditionB = conditionB;
} public void await_A(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" await_A time is "+System.currentTimeMillis());
conditionA.await();
System.out.println(Thread.currentThread().getName()+" after await_A info...");
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
} public void await_B(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" await_B time is "+System.currentTimeMillis());
conditionB.await();
System.out.println(Thread.currentThread().getName()+" after_B await info...");
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
} public void signal_A(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" signal_A time is "+System.currentTimeMillis());
conditionA.signal();
} finally {
lock.unlock();
}
} public void signal_B(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" signal_B time is "+System.currentTimeMillis());
conditionB.signal();
} finally {
lock.unlock();
}
} public void run() {
String tname = Thread.currentThread().getName();
if (tname.equals("A")) {
await_A();
} else if (tname.equals("B")) {
await_B();
}
} }
/**
* 测试类
* @author ko
*
*/
public class Test { public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock(); Condition conditionA = lock.newCondition();
Condition conditionB = lock.newCondition();
MyService service = new MyService(lock,conditionA,conditionB); Thread tA = new Thread(service);
tA.setName("A");
tA.start(); Thread tB = new Thread(service);
tB.setName("B");
tB.start(); try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} service.signal_A();
}
}
A await_A time is 1501482321344
B await_B time is 1501482321346
main signal_A time is 1501482324344
A after await_A info...
可以看到只唤醒了A线程。。。
一对一的生产者消费者
/**
* 生产者和消费者一对一
* @author ko
*
*/
public class MyService { protected ReentrantLock lock = new ReentrantLock();
protected Condition condition = lock.newCondition();
protected boolean hasValue = false; public void set(){
try {
lock.lock();
while (hasValue == true) {
condition.await();
}
System.out.println("★");
hasValue = true;
condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
} public void get(){
try {
lock.lock();
while (hasValue == false) {
condition.await();
}
System.out.println("☆");
hasValue = false;
condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
} }
/**
* 生产者
* @author ko
*
*/
public class Producer implements Runnable { protected MyService myService; public Producer(MyService myService) {
super();
this.myService = myService;
} public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
myService.set();
}
} }
/**
* 消费者
* @author ko
*
*/
public class Customer implements Runnable { protected MyService myService; public Customer(MyService myService) {
super();
this.myService = myService;
} public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
myService.get();
}
} }
/**
* 测试类
* @author ko
*
*/
public class Test { public static void main(String[] args) {
MyService myService = new MyService();
Producer p = new Producer(myService);
Customer c = new Customer(myService); new Thread(p).start();
new Thread(c).start(); }
}
打印结果
多对多的生产者消费者
/**
* 测试类
* @author ko
*
*/
public class Test { public static void main(String[] args) {
MyService myService = new MyService(); for (int i = 0; i < 10; i++) {
new Thread(new Producer(myService)).start();
new Thread(new Customer(myService)).start();
} }
}
/**
* 生产者和消费者多对多
* @author ko
*
*/
public class MyService { protected ReentrantLock lock = new ReentrantLock();
protected Condition condition = lock.newCondition();
protected boolean hasValue = false; public void set(){
try {
lock.lock();
while (hasValue == true) {
System.out.println("有可能★连续打印");
condition.await();
}
System.out.println("★");
hasValue = true;
condition.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
} public void get(){
try {
lock.lock();
while (hasValue == false) {
System.out.println("有可能☆连续打印");
condition.await();
}
System.out.println("☆");
hasValue = false;
condition.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
} }
要注意的是由于现在是多个生产者消费者,所以condition.signal()要改为condition.signalAll(),其它代码不变。
查看打印结果,发现★和☆总是间隔打印,但是 有可能★连续打印 和 有可能☆连续打印 却有可能连续打印,这是因为改为signalAll后唤醒的是所有线程,有可能再次把自己唤醒,所以会出现这种情况。
公平锁与非公平锁
公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,而非公平锁是一种抢占机制,随机的。
还是上面的代码,给ReentrantLock换个有isFair参数的构造方法,new ReentrantLock(isFair) true就是公平锁,false就是非公平锁。再给打印的语句加上线程名,当为true时,线程是按顺序打印,为false时随机打印。
方法getHoldCount()的使用
getHoldCount()表示当前线程获取锁的个数
public class MyService {
protected ReentrantLock lock = new ReentrantLock(true);
public void method1(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"线程保持lock锁的个数:"+lock.getHoldCount()+" method1");
method2();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void method2(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"线程保持lock锁的个数:"+lock.getHoldCount()+" method2");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class ThreadA extends Thread { protected MyService myService; public ThreadA(MyService myService) {
super();
this.myService = myService;
} public void run() {
myService.method1();
} }
public class Test {
public static void main(String[] args) {
MyService myService = new MyService();
new ThreadA(myService).start();
}
}
getQueueLength()方法使用
getQueueLength()表示等待获取lock锁的估计线程个数。
public class MyService {
protected ReentrantLock lock = new ReentrantLock(); public void getql(){
System.out.println("等待获取lock锁的估计线程个数:"+lock.getQueueLength()+" method1");
} public void synmethod(){
System.out.println(Thread.currentThread().getName()+"开始了。。。");
lock.lock();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
}
public class ThreadA extends Thread {
protected MyService myService; public ThreadA(MyService myService) {
super();
this.myService = myService;
} public void run() {
myService.synmethod();
}
}
public class Test {
public static void main(String[] args) {
MyService myService = new MyService();
new ThreadA(myService).start();
new ThreadA(myService).start();
new ThreadA(myService).start();
new ThreadA(myService).start();
new ThreadA(myService).start();
while (true) {
myService.getql();
try {
Thread.sleep(900);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
getWaitQueueLength(condition)的用法
getWaitQueueLength(condition) 表示返回等待与此锁相关的给定条件condition的线程估计数。比如有3个线程都执行了同一个condition的await方法,那么调用getWaitQueueLength(condition)返回的就是3.
public class MyService {
protected ReentrantLock lock = new ReentrantLock();
protected Condition condition = lock.newCondition();
protected Condition condition1 = lock.newCondition(); public void synmethod(){
System.out.println(Thread.currentThread().getName()+"开始了。。。");
lock.lock();
System.out.println("进入lock锁与condition关联的的估计线程个数:"+lock.getWaitQueueLength(condition));
System.out.println("进入lock锁与condition1关联的的估计线程个数:"+lock.getWaitQueueLength(condition1));
System.out.println("");
try {
if (!Thread.currentThread().getName().contains("2")) {
condition.await();
}else{
condition1.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
}
public class Test {
public static void main(String[] args) {
MyService myService = new MyService();
new ThreadA(myService).start();
new ThreadA(myService).start();
new ThreadA(myService).start();
new ThreadA(myService).start();
new ThreadA(myService).start();
}
}
hasQueuedThread(thread)和hasQueuedThreads()的使用
hasQueuedThread(thread)返回的是线程thread是否在等待获取lock锁
hasQueuedThreads()返回的是是否有线程正在等待获取lock锁
public class MyService {
protected ReentrantLock lock = new ReentrantLock();
protected Condition condition = lock.newCondition(); public void hasa(Thread thread){
if (lock.hasQueuedThread(thread)) {
System.out.println(thread.getName()+"正在等待获取lock锁。。。");
}else{
System.out.println(thread.getName()+"不在等待获取lock锁。。。");
}
System.out.println("是否有线程在等待获取lock锁:"+lock.hasQueuedThreads());
System.out.println("");
} public void synmethod(){
System.out.println(Thread.currentThread().getName()+"开始了。。。");
lock.lock(); if (Thread.currentThread().getName().contains("1")) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
}
}
public class Test {
public static void main(String[] args) {
MyService myService = new MyService();
ThreadA ta = new ThreadA(myService);
ta.start();
ThreadA tb = new ThreadA(myService);
tb.start();
while (true) {
myService.hasa(ta);
myService.hasa(tb);
System.out.println(""+ta.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
hasWaiters(condition)的用法
hasWaiters(condition)表示是否有线程进入了lock锁与condition相关联的等待中。
public class MyService {
protected ReentrantLock lock = new ReentrantLock();
protected Condition condition = lock.newCondition(); public void synmethod(){
System.out.println(Thread.currentThread().getName()+"开始了。。。");
lock.lock(); System.out.println("是否有线程进入了lock锁与condition相关联的等待中:"+lock.hasWaiters(condition));
if (Thread.currentThread().getName().contains("0")) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
}
public class Test {
public static void main(String[] args) {
MyService myService = new MyService(); ThreadA ta = new ThreadA(myService);
ta.start(); try {
Thread.sleep(3500);
} catch (InterruptedException e) {
e.printStackTrace();
} ThreadA tb = new ThreadA(myService);
tb.start(); }
}
方法isFair()、isHeldByCurrentThread()、isLocked()的使用
isFair()判断线程锁是不是公平锁
isHeldByCurrentThread()查询当前线程是否保持此锁定
isLocked()查询此锁定是否由任意线程保持
public class MyService {
protected ReentrantLock lock = new ReentrantLock(true);
protected Condition condition = lock.newCondition(); public void synmethod(){
System.out.println("lock锁是不是公平锁:"+lock.isFair());
System.out.println("lock锁定是否由任意线程保持:"+lock.isLocked());
System.out.println(Thread.currentThread().getName()+"是否保持lock锁定:"+lock.isHeldByCurrentThread());
lock.lock();
System.out.println("lock锁定是否由任意线程保持:"+lock.isLocked());
System.out.println(Thread.currentThread().getName()+"是否保持lock锁定:"+lock.isHeldByCurrentThread());
lock.unlock();
}
}
public class Test {
public static void main(String[] args) {
MyService myService = new MyService(); ThreadA ta = new ThreadA(myService);
ta.start();
}
}
lockInterruptibly()方法的使用
lockInterruptibly()比lock()获取锁之前多了个判断,如果当前线程未被中断,则获取锁定,如果已被中断,则抛出java.lang.InterruptedException异常。
public class MyService {
protected ReentrantLock lock = new ReentrantLock(true);
protected Condition condition = lock.newCondition(); public void synmethod(){
try {
System.out.println(Thread.currentThread().getName()+" begin "+new Date().toString());
for (int i = 0; i < Integer.MAX_VALUE/20; i++) {// 大概会延长7 8s,这里不用sleep延长线程时间,而是这样写,是因为调用线程的interrupt()方法时,如果线程在sleep会报异常
Math.random();
}
if(new Random().nextInt(5)%2==0){// 随机
System.out.println(Thread.currentThread().getName()+" 使用的是lock() ");
lock.lock();
}else{
System.out.println(Thread.currentThread().getName()+" 使用的是lockInterruptibly() ");
lock.lockInterruptibly();
} System.out.println(Thread.currentThread().getName()+" lock 1 "+new Date().toString());
for (int i = 0; i < Integer.MAX_VALUE/20; i++) {// 同上
Math.random();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+" lock 2 "+new Date().toString());
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
System.out.println(Thread.currentThread().getName()+" end "+new Date().toString());
}
}
}
/**
* 测试类
* @author ko
*
*/
public class Test {
public static void main(String[] args) {
MyService myService = new MyService(); ThreadA taa = new ThreadA(myService);
taa.setName("taa");
taa.start(); try {
Thread.sleep(1500);// 等前面的线程都启动好
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("taa interrupt "+new Date().toString());
taa.interrupt();// 打标记 这个时候taa还没有进入lock锁里 }
}
代码里采用了随机的处理,有的时候使用的是lock(),有的时候使用的是lockInterruptibly(),多运行几遍就能得到两种结果。
lock.tryLock()、lock.tryLock(timeout, unit)方法使用
lock.tryLock()) 立即返回,获得锁返回true,没获得锁返回false
lock.tryLock(3, TimeUnit.SECONDS) 等待3s,3s后,获得锁返回true,没获得锁返回false
public class MyService {
protected ReentrantLock lock = new ReentrantLock(true);
protected Condition condition = lock.newCondition(); public void synmethod(){
try {
System.out.println(Thread.currentThread().getName()+"进入方法"+new Date().toString()); if (lock.tryLock()) {// 立即返回,获得锁返回true,没获得锁返回false
System.out.println(Thread.currentThread().getName()+"获得锁");
} else {
System.out.println(Thread.currentThread().getName()+"没有获得锁");
} // if (lock.tryLock(3, TimeUnit.SECONDS)) {// 等待3s,3s后,获得锁返回true,没获得锁返回false
// System.out.println(Thread.currentThread().getName()+"获得锁的时间"+new Date().toString());
// Thread.sleep(10000);
// } else {
// System.out.println(Thread.currentThread().getName()+"没有获得锁");
// } System.out.println(Thread.currentThread().getName()+"方法结束"+new Date().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 测试类
* @author ko
*
*/
public class Test {
public static void main(String[] args) {
MyService myService = new MyService(); ThreadA ta = new ThreadA(myService);
ta.setName("ta");
ta.start(); ThreadA taa = new ThreadA(myService);
taa.setName("taa");
taa.start();
}
}
awaitUninterruptibly()方法使用
当在线程等待的时候,如果外部要中断该线程,不会报InterruptedException异常,而await()会报异常
public class MyService {
protected ReentrantLock lock = new ReentrantLock(true);
protected Condition condition = lock.newCondition(); public void synmethod(){
try {
System.out.println(Thread.currentThread().getName()+"进入方法"+new Date().toString()); lock.lock(); if (new Random().nextInt(5)%2 == 0) {
System.out.println(Thread.currentThread().getName()+"走的是await()");
condition.await();
} else {
System.out.println(Thread.currentThread().getName()+"走的是awaitUninterruptibly()");
condition.awaitUninterruptibly();
} } catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"方法结束"+new Date().toString());
lock.unlock();
}
}
}
/**
* 测试类
* @author ko
*
*/
public class Test {
public static void main(String[] args) {
MyService myService = new MyService(); ThreadA taa = new ThreadA(myService);
taa.setName("taa");
taa.start(); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
taa.interrupt();// 打标记
}
}
awaitUntil(Time time)方法使用
awaitUntil(Time time)和await()一样会使当前线程进入等待状态,不过它有个截止时间,到了time这个时间,自动唤醒。
public class MyService {
protected ReentrantLock lock = new ReentrantLock(true);
protected Condition condition = lock.newCondition(); public void synmethod(){
try {
System.out.println(Thread.currentThread().getName()+"进入方法"+new Date().toString()); lock.lock(); Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
System.out.println("begin awaitUntil "+new Date().toString());
condition.awaitUntil(calendar.getTime());//
System.out.println("after awaitUntil "+new Date().toString()); } catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"方法结束"+new Date().toString());
lock.unlock();
}
}
}
/**
* 测试类
* @author ko
*
*/
public class Test {
public static void main(String[] args) {
MyService myService = new MyService(); ThreadA taa = new ThreadA(myService);
taa.setName("taa");
taa.start();
}
}
使用Condition实现顺序执行
/**
* 利用condition实现顺序执行
* @author ko
*
*/
public class MyService implements Runnable{
protected ReentrantLock lock;
protected Condition signalCondition;// 在某个线程里负责等待
protected Condition awaitCondition;// 在某个线程里负责唤醒 public MyService(ReentrantLock lock, Condition signalCondition, Condition awaitCondition) {
super();
this.lock = lock;
this.signalCondition = signalCondition;
this.awaitCondition = awaitCondition;
} public void print(Condition signalCondition, Condition awaitCondition) throws InterruptedException{
lock.lock();
for (int j = 0; j < 10; j++) {
for (int i = 1; i < 4; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
System.out.println("");
signalCondition.signal();
awaitCondition.await();
}
lock.unlock();
} public void run() {
try {
print(signalCondition, awaitCondition);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
myservice
/**
* 测试类
* @author ko
*
*/
public class Test {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition conditionA = lock.newCondition();
Condition conditionB = lock.newCondition();
Condition conditionC = lock.newCondition(); MyService myService = new MyService(lock, conditionB, conditionA); new Thread(new MyService(lock, conditionB, conditionA),"thread a").start();
new Thread(new MyService(lock, conditionC, conditionB),"thread b").start();
new Thread(new MyService(lock, conditionA, conditionC),"thread c").start(); }
}
test
thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3 thread a 1
thread a 2
thread a 3 thread b 1
thread b 2
thread b 3 thread c 1
thread c 2
thread c 3
打印结果
java并发之ReentrantLock学习理解的更多相关文章
- Java并发之ReentrantLock源码解析(四)
Condition 在上一章中,我们大概了解了Condition的使用,下面我们来看看Condition再juc的实现.juc下Condition本质上是一个接口,它只定义了这个接口的使用方式,具体的 ...
- Java并发之ReentrantLock
一.ReentrantLock简介 ReentrantLock字面意义上理解为可重入锁.那么怎么理解可重入这个概念呢?或者说和我们经常用的synchronized又什么区别呢? ReentrantLo ...
- Java并发之ReentrantLock详解
一.入题 ReentrantLock是Java并发包中互斥锁,它有公平锁和非公平锁两种实现方式,以lock()为例,其使用方式为: ReentrantLock takeLock = new Reent ...
- Java并发之ReentrantLock源码解析(一)
ReentrantLock ReentrantLock是一种可重入的互斥锁,它的行为和作用与关键字synchronized有些类似,在并发场景下可以让多个线程按照一定的顺序访问同一资源.相比synch ...
- Java并发之ReentrantLock源码解析(三)
ReentrantLock和BlockingQueue 首先,看到这个标题,不要怀疑自己进错文章,也不要怀疑笔者写错,哈哈.本章笔者会从BlockingQueue(阻塞队列)的角度,看看juc包下的阻 ...
- java高并发----个人学习理解汇总记录
1.首先,需要理解几个概念 1.同步(Synchronous):同步方法调用一旦开始,调用者必须等到前面的方法调用返回后,才能继续后续的行为,依次直到完成所有. 2.异步(Asynchronous): ...
- Java并发之ReentrantLock源码解析(二)
在了解如何加锁时候,我们再来了解如何解锁.可重入互斥锁ReentrantLock的解锁方法unlock()并不区分是公平锁还是非公平锁,Sync类并没有实现release(int arg)方法,这里会 ...
- 深入理解Java并发之synchronized实现原理
深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...
- Java 8 Lambda表达式学习和理解
Java 8 Lambda表达式和理解 说明:部分资料来源于网络 时间:20190704 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性.Lambda 允许把函数作为一 ...
随机推荐
- 【翻译】在Ext JS应用程序中使用自定义图标
原文:Using Custom Icons in Your Ext JS App 作者:Lee BoonstraLee is a technical trainer at Sencha. She's ...
- Android驱动中的Kconfig文件与Makefile文件
内核源码树的目录下都有两个文档Kconfig(2.4版本是Config.in)和Makefile.分布到各目录的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文 ...
- 让App中加入LruCache缓存,轻松解决图片过多造成的OOM
上次有过电话面试中问到Android中的缓存策略,当时模糊不清的回答,现在好好理一下吧. Android中一般情况下采取的缓存策略是使用二级缓存,即内存缓存+硬盘缓存->LruCache+Dis ...
- JQuery UI - resizable
·概述 resizable插件可以让选中的元素具有改变尺寸的功能. 官方示例地址:http://jqueryui.com/demos/resizable/ 所有的事件回调函数都有两个参数:eve ...
- Android全局异常处理 实现自己定义做强制退出和carsh日志抓取
在做android项目开发时,大家都知道都会遇到程序报错或者Anr异常,会弹出来一个强制退出的弹出框,对于开发人员是好事,但是对于用户体验和 UI实在毫无违和感,别说用户接受不了,就连我们自己本身可能 ...
- WinCE系统声音定制
作者:ARM-WinCE 2010的第一篇Blog,介绍一下WinCE系统声音的定制.说白了,就是设置注册表.WinCE系统启动的开机音乐,点击触摸屏以及键盘输入的按键音,还有系统运行过程中的各种声音 ...
- break和continue的简单介绍
1.break break 用于完全结束一个循环,跳出循环体!不管是哪种循环,如果在程序中遇到Break,系统将完全结束该循环,开始执行循环之后的代码: public class TestBreak ...
- 恶补web之八:jQuery(2)
jquery中非常重要的部分,就是操作dom的能力: text() - 设置或返回所选元素的文本内容 html() - 设置或返回所选元素的内容(包括html标记) val() - 设置或返回表单字段 ...
- ELF 文件 动态链接 - 地址无关代码(GOT)
Linux 系统中,ELF动态链接文件被称为 动态共享对象(DSO,Dynamic Shared Object),简称共享对象 文件拓展名为".so" 动态链接下 一个程序可以被分 ...
- Java的运行原理
在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器.这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口.编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由 ...