标签:finally obj stat ali 访问 als void adl boolean
1.锁是干什么用的
锁一般来说用作资源控制,限制资源访问,防止在并发环境下造成数据错误
2.重入锁
重入锁也叫作递归锁,指的是同一个线程外层函数获取到一把锁后,内层函数同样具有这把锁的控制权限
synchronized和ReentrantLock就是重入锁对应的实现
synchronized重量级的锁
ReentrantLock轻量级的锁 lock()代表加入锁 unlock()代表释放锁
不可重入锁:说明当没有释放该锁时。其他线程获取该锁会进行等待
public class MyLock {
//标识锁是否可用 如果值为 true代表有线程正在使用该 锁 ,如果为false代表没有人使用锁
private boolean isLocked=false;
//获取锁:加锁
public synchronized void lock() throws InterruptedException {
//判断当前该锁是否正在使用
while (isLocked){
wait();
}
//当前没有人使用情况 下就占用该锁
isLocked=true;
}
//释放锁
public synchronized void unLock(){
//将当前锁资源释放
isLocked=false;
//唤起正在等待使用锁的线程
notify();
}
}
public class MyLockTest {
MyLock myLock=new MyLock();
//A业务
public void print() throws InterruptedException {
//获取一把锁
myLock.lock();
System.out.println("print业务方法");
doAdd();
//释放锁
myLock.unLock();
}
//B业务方法
public void doAdd() throws InterruptedException {
//获取一把锁
myLock.lock();
System.out.println("aoAdd方法");
//释放锁
myLock.unLock();
}
public static void main(String[] args) throws InterruptedException {
MyLockTest myLockTest=new MyLockTest();
myLockTest.print();
}
}
控制台结果:
当前效果就造成了死锁

synchronized可重入性:如果当前A持有一把锁,在A业务内部调用B,那么B也同样拥有这把锁的使用权限
编写测试代码:
MyLock myLock=new MyLock();
//A业务
public synchronized void print() throws InterruptedException {
System.out.println("print业务方法");
doAdd();
}
//B业务方法
public synchronized void doAdd() throws InterruptedException {
System.out.println("aoAdd方法");
}
public static void main(String[] args) throws InterruptedException {
MyLockTest myLockTest=new MyLockTest();
myLockTest.print();
}
控制台结果:

ReentrantLock同样具有可重入性
编写测试代码:
public class MyLockTest {
//创建锁对象
Lock lock=new ReentrantLock();
//A业务
public void print() throws InterruptedException {
//获取了一把锁
lock.lock();
System.out.println("print业务方法");
doAdd();
//释放锁
lock.unlock();
}
//B业务方法
public void doAdd() throws InterruptedException {
//获取一把锁
lock.lock();
System.out.println("aoAdd方法");
//释放锁
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
MyLockTest myLockTest=new MyLockTest();
myLockTest.print();
}
}
控制台结果:

3. 读写锁
并发线程下,所有线程都执行读的操作,会不会有问题
并发线程下,部分读部分写会不会有问题 会发生写冲突
并发线程下,所有线程都执行写会不会有问题 会发生写冲突
编写测试代码:
//创建一个集合
static Map<String,String> map=new HashMap<String,String>();
//创建一个读写锁
static ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
//获取读锁
static Lock readLock=lock.readLock();
//获取写锁
static Lock writeLock=lock.writeLock();
//写操作
public Object put(String key,String value){
writeLock.lock();
try {
System.out.println("Write正在执行写操作~");
Thread.sleep(100);
String put = map.put(key, value);
System.out.println("Write写操作执行完毕~");
return put;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
writeLock.unlock();
}
return null;
}
//写操作
public Object get(String key){
readLock.lock();
try {
System.out.println("Read正在执行读操作~");
Thread.sleep(100);
String value = map.get(key);
System.out.println("Read读操作执行完毕~");
return value;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
readLock.unlock();
}
return null;
}
public static void main(String[] args) {
ReadWriteLock lock=new ReadWriteLock();
for (int i = 0; i < 10; i++) {
int finalI = i;
new Thread(()->{
try {
//写操作
lock.put(finalI +"","value"+finalI);
//读操作
System.out.println(lock.get(finalI+""));
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
控制台 结果:
我们可以看出是当所有写操作都执行完毕后才开始执行读操作

4. 乐观锁
总认为不会发生并发问题,每一次取数据时总认为其他线程不会对该数据先进性更改,但是在更新时会判断其他线程在这之前有
没有对该数据进行修改,
数据库当中常用方案:版本号控制
5.悲观锁
总是假设最坏的情况,每次取数据时,都会认为其他线程会对该数据进行修改,所以会进行加锁
其他线程访问的时候会阻塞等待,例如在数据库当中可以使用行锁,表锁以及读写锁等方式实现
标签:finally obj stat ali 访问 als void adl boolean
原文地址:https://www.cnblogs.com/tinghao/p/12567786.html