【锁】作为并发共享数据保证一致性的工具,显然这个工具的地位是非常重要的,这里把这个锁的原理以及实现手动打造出来,为以后对锁的理解打下更好的基础,以后学习juc的锁会容易许多。
以前使用的【锁】可以理解为内置锁,也就是系统提供好的,内置锁的特点是【可重入】,举个简单的例子:你去朋友家里,进到朋友家的客厅了,你就有权利进到他家的卫生间,进到他家的厨房等,这个就叫做可重入。
所以在我们的多线程里面,当某一个线程试图获取一个已经由它自己持有的锁的时候,那么这个请求会立刻成功,我们每一个锁都有计数器,再次进入以后将这个锁再加1,当退出来了这个计数器会减一个1,直到这个计数器等于0的时候,锁释放。如果没有可重入锁的支持,在第二次企图获得锁的时候可能就会进入死锁状态。可重入锁在后期随处可见。
内置锁都支持可重入。
package com.sxt.others;
/**
* 可重入锁: 锁可以延续使用
*
* @author
*
*/
public class LockTest01 {
public void test() {
// 第一次获得锁
synchronized(this) {
while(true) {
// 第二次获得同样的锁
synchronized(this) {
System.out.println("ReentrantLock!");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new LockTest01().test();
}
}
package com.sxt.others;
/**
* 不可重入锁: 锁不可以延续使用
*
* @author
*
*/
public class LockTest02 {
Lock lock = new Lock();
public void a() throws InterruptedException {
lock.lock();
doSomething();
lock.unlock();
}
//不可重入
public void doSomething() throws InterruptedException {
lock.lock();
//...................
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
LockTest02 test = new LockTest02();
test.a();
test.doSomething();
}
}
// 不可重入锁
class Lock{
//是否占用
private boolean isLocked = false;
//使用锁
public synchronized void lock() throws InterruptedException {
while(isLocked) {
wait();
}
isLocked = true;
}
//释放锁
public synchronized void unlock() {
isLocked = false;
notify();
}
}
package com.sxt.others;
/**
* 可重入锁: 锁可以延续使用 + 计数器
*
* @author
*
*/
public class LockTest03 {
ReLock lock = new ReLock();
public void a() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
doSomething();
lock.unlock();
System.out.println(lock.getHoldCount());
}
//不可重入
public void doSomething() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
//...................
lock.unlock();
System.out.println(lock.getHoldCount());
}
public static void main(String[] args) throws InterruptedException {
LockTest03 test = new LockTest03();
test.a();
Thread.sleep(1000);
System.out.println(test.lock.getHoldCount());
}
}
// 可重入锁
class ReLock{
//是否占用
private boolean isLocked = false;
private Thread lockedBy = null; //存储线程
private int holdCount = 0;
//使用锁
public synchronized void lock() throws InterruptedException {
Thread t = Thread.currentThread();
while(isLocked && lockedBy != t) {
wait();
}
isLocked = true;
lockedBy = t;
holdCount ++;
}
//释放锁
public synchronized void unlock() {
if(Thread.currentThread() == lockedBy) {
holdCount --;
if(holdCount ==0) {
isLocked = false;
notify();
lockedBy = null;
}
}
}
public int getHoldCount() {
return holdCount;
}
}
package com.sxt.others;
import java.util.concurrent.locks.ReentrantLock;
/**
* 可重入锁: 锁可以延续使用 + 计数器
* ReentrantLock
* @author
*
*/
public class LockTest04 {
ReentrantLock lock = new ReentrantLock();
public void a() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
doSomething();
lock.unlock();
System.out.println(lock.getHoldCount());
}
//不可重入
public void doSomething() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
//...................
lock.unlock();
System.out.println(lock.getHoldCount());
}
public static void main(String[] args) throws InterruptedException {
LockTest04 test = new LockTest04();
test.a();
Thread.sleep(1000);
System.out.println(test.lock.getHoldCount());
}
}