目录
ReentrantLock:synchronized的增强版
特性:效率较高,灵活,可感知获取锁,读写分离控制(读多写少),读读并行,读写串行,写写串行
生活中,我们在门上可以见到锁,在手机上可以见到锁,在电脑上,汽车上,保险柜上......等等,可见锁在我们生活中是一个随处可件的物品,但我们今天要讲的是,java中的锁。本篇文章仅博主个人观点,仅供参考,共同进步,感谢博友支持。
什么是锁?
将某种资源私有化的一种物品,没错java里面的锁也是这种特性,它可以让某个方法,某个变量或某个通道,在某个时刻下只能被一个线程占用。只有当这个锁释放了,另外的线程才可以使用。例子:上厕所,一个同事上厕所把门锁上,这个时候厕所就被上锁了,别人要想进去,只能等这位同事释放锁后出来,其他同事才可进入。这个厕所可以看成是临界区,同事就是线程。
临界区?
多个线程共享同一个资源的情况,为了防止出现数据不一致情况的发生,人们引入了临界区的概念。临界区是一个用来访问共享资源的代码块,同一时间内只运行一个线程进入。
有几种锁?
java体系中有几种锁呢?
synchronized(不公平)
ReentrantLock 重入锁 (可公平可不公平)
ReadWriteLock 读写锁(不公平)
公平?不公平
公平锁会按照时间的先后顺序来给予锁
不公平锁在等待队列随机挑选一个来给予锁
例子:银行办理业务排队,一堆人要办业务,都围在窗口前,业务员也顾不得前后,顺便就找个人办理,这样是不公平的,而公平的则是先到先办理后到后办理
怎么用锁?
要想知道怎么用锁需要清楚每个锁的特点,才能对症下药。
例子:在不带锁的情况下,线程同时进入方法,如果业务处理的是减库存又或者是加减金额,就会出现由高并发下带来的问题,导致数据错误混乱
public class SynchronizedDemo {
public static void addAmount() {
System.out.println("进入方法");
try {
// 模拟业务处理
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("退出方法");
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(() -> addAmount()).start();
}
}
}
结果:
进入方法
进入方法
进入方法
退出方法
退出方法
退出方法
synchronized
特性:可重入,可见性
缺点:效率比较低,不够灵活,不可中断,无法感知获取锁
package com.zqh.www;
public class SynchronizedDemo {
public synchronized static void addAmount() {
System.out.println("进入方法");
try {
// 模拟业务处理
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("退出方法");
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(() -> addAmount()).start();
}
}
}
进入方法
退出方法
进入方法
退出方法
进入方法
退出方法
ReentrantLock:synchronized的增强版
特性:效率较高,灵活,可感知获取锁,可公平可非公平,可中断
缺点:需在finally释放锁
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
private static ReentrantLock reentrantLock = new ReentrantLock();
public static void addAmount() {
reentrantLock.lock();
try {
System.out.println("进入方法");
try {
// 模拟业务处理
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("退出方法");
} finally {
reentrantLock.unlock();
}
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(() -> addAmount()).start();
}
}
}
进入方法
退出方法
进入方法
退出方法
进入方法
退出方法
ReadWriteLock
特性:效率较高,灵活,可感知获取锁,读写分离控制(读多写少),读读并行,读写串行,写写串行
缺点:需在finally释放锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private static Lock readLock = reentrantReadWriteLock.readLock();
private static Lock writeLock = reentrantReadWriteLock.writeLock();
private static volatile int value = 0;
public static void readAmount() {
readLock.lock();
try {
System.out.println("查看金额:" + value);
try {
// 模拟业务处理
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
readLock.unlock();
}
}
public static void addAmount() {
writeLock.lock();
try {
System.out.println("进入方法");
try {
// 模拟业务处理
++value;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("退出方法");
} finally {
writeLock.unlock();
}
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(() -> readAmount()).start();
}
for (int i = 0; i < 3; i++) {
new Thread(() -> addAmount()).start();
}
}
}
标签:Thread,void,System,public,static,方法,什么
From: https://blog.csdn.net/m0_59679869/article/details/139510475