1、简单实现(不可重入)
Lock的实现类:
package mylock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock implements Lock {
boolean isHeld = false;//当前锁有没有被线程持有
@Override
public synchronized void lock() {
if (isHeld) {//如果被线程持有,则当前线程等待
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isHeld = true;//被被线程持有,则当前线程获取到锁
}
@Override
public synchronized void unlock() {
notify();//随机唤醒一个等待的线程
isHeld=false;//没有被持有
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public Condition newCondition() {
return null;
}
}
测试类:
package mylock;
public class Test {
static MyLock myLock=new MyLock();
static int count = 0;
public static void increase() {
myLock.lock();
count++;
myLock.unlock();
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 100; j++) {
increase();
}
}
).start();
}
Thread.sleep(1000);
System.out.println(count);//1000
}
}
验证不可重入:
package mylock;
public class Test2 {
static MyLock lock=new MyLock();
void method1(){
lock.lock();
System.out.println("进入方法1");
method2();
lock.unlock();
}
void method2(){
lock.lock();
System.out.println("进入方法2");
lock.unlock();
}
public static void main(String[]a){
Test2 demo=new Test2();
demo.method1();
}
}
/*
输出:
进入方法1
*/
主线程进执行method1时,还没有线程获取锁,在lock()方法中主线程将isHeld改为true。当执行method2时,主线程执行到lock()方法,这时isHeld已经为true,所以经被持有,也就是被自己持有,所以进行等待(不是死锁)。
2、可重入的实现
package mylock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock implements Lock {
private boolean isHeld = false;//当前锁有没有被线程持有
private Thread holdLockThread = null;//记录持有锁的线程
private int reentryCount = 0;//记录重入次数
@Override
public synchronized void lock() {
if (isHeld && Thread.currentThread() != holdLockThread) {//如果锁被线程持有,并且当前线程不是持有锁的线程,则当前线程等待
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isHeld = true;//被被线程持有,则当前线程获取到锁
holdLockThread = Thread.currentThread();//持有锁的线程为当前线程
reentryCount++;//重入次数加1
}
@Override
public synchronized void unlock() {
if (Thread.currentThread() == holdLockThread) {//如果当前线程是持有锁的线程
reentryCount--;//重入次数减1
if (reentryCount == 0) {//如果重入次数为0了,就该释放锁了
notify();//随机唤醒一个等待的线程
isHeld = false;//没有被持有
}
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public Condition newCondition() {
return null;
}
}
验证方式和上面一样,这下就能在method1中进入method2了。