电子书:
锁池(对象头),等待池(waitset)。
-------------------------------------04---71-----------------------------------------
测试可重入:
代码:
测试可以重入的:
注意a调用b,此时a锁,b也锁,是可重入的锁。就是我在一个加锁的方法里面调用另一个加锁的方法,是可以调用的。
-------------------------------------04 72--------------------------------------------
测试可打断:
没有被打断的情况。
package cn.itcast.test;
import lombok.extern.slf4j.Slf4j;
import java.sql.Time;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static cn.itcast.n2.util.Sleeper.sleep;
@Slf4j(topic = "c.Test22")
public class Test22 {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println("test");
try {
if (! lock.tryLock(2, TimeUnit.SECONDS)) {
System.out.println("获取不到锁 in time");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("no test");
return;
}
try {
System.out.println("get");
} finally {
lock.unlock();
}
}, "t1");
// 主线程先lock
lock.lock();
System.out.println("get");
t1.start();
sleep(4);
System.out.println("release");
lock.unlock();
}
}
打断:
打断是我自己的线程打断我自己不是别人打断我。
用简单的lock方法,就是死等的,不能打断。
-------------------------------------04---73----------------------------------------
可打断是被动的。
锁超时是尝试获取锁超时,之后直接返回不在阻塞队列里面阻塞了。
可以是带参数的也可以是不带参数的。
测试可超时:
package cn.itcast.test;
import lombok.extern.slf4j.Slf4j;
import java.sql.Time;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static cn.itcast.n2.util.Sleeper.sleep;
@Slf4j(topic = "c.Test22")
public class Test22 {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
log.debug("尝试获得锁");
try {
if (! lock.tryLock(2, TimeUnit.SECONDS)) {
log.debug("获取不到锁");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
log.debug("获取不到锁");
return;
}
try {
log.debug("获得到锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
log.debug("获得到锁");
t1.start();
sleep(4);
log.debug("释放了锁");
lock.unlock();
}
}
tryLock也是可以被打断的。
--------------------------------------04-------74--------------------------------------------
锁的超时解决哲学家就餐问题。
哲学家就餐:这个就是把syn变为reentrantLock
-------------------------------------04--75---------------------------------------
公平锁和非公平锁。
默认是不公平的。
-----------------------------------04---76------------------------------------------
条件变量是重点的。
await被唤醒或者打断的话就进入到reentrantlock的等待队列里面的。
锁是一样的就是等待的屋子是不一样的,唤醒的屋子里的人也是不一样的。
代码:
package cn.itcast.test;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import static cn.itcast.n2.util.Sleeper.sleep;
@Slf4j(topic = "c.Test24")
public class Test24 {
static final Object room = new Object();
static boolean hasCigarette = false;
static boolean hasTakeout = false;
static ReentrantLock ROOM = new ReentrantLock();
// 等待烟的休息室
static Condition waitCigaretteSet = ROOM.newCondition();
// 等外卖的休息室
static Condition waitTakeoutSet = ROOM.newCondition();
public static void main(String[] args) {
new Thread(() -> {
ROOM.lock();
try {
log.debug("有烟没?[{}]", hasCigarette);
while (!hasCigarette) {
log.debug("没烟,先歇会!");
try {
waitCigaretteSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("可以开始干活了");
} finally {
ROOM.unlock();
}
}, "小南").start();
new Thread(() -> {
ROOM.lock();
try {
log.debug("外卖送到没?[{}]", hasTakeout);
while (!hasTakeout) {
log.debug("没外卖,先歇会!");
try {
waitTakeoutSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("可以开始干活了");
} finally {
ROOM.unlock();
}
}, "小女").start();
sleep(1);
new Thread(() -> {
ROOM.lock();
try {
hasTakeout = true;
waitTakeoutSet.signal();
} finally {
ROOM.unlock();
}
}, "送外卖的").start();
sleep(1);
new Thread(() -> {
ROOM.lock();
try {
hasCigarette = true;
waitCigaretteSet.signal();
} finally {
ROOM.unlock();
}
}, "送烟的").start();
}
}
----------------------------04------------78--79-----