重入锁
ReentrantLock,是对synchronized的升级,synchronized是通过JVM实现的,ReentrantLock是通过JDK实现的。
重入锁的特点:
重入锁指可以给同一个资源添加多个锁,并且解锁的方式与synchronized也不同,synchronized的锁是当线程执行完业务逻辑之后自动释放,ReentrantLock的锁必须手动释放。
-
可重入,可以给同一个资源同时添加多把锁,对应的解锁的次数必须与上锁的次数相同,否则就会出现程序不继续执行的情况。
-
可中断,指某个线程在等待获取锁的过程中可主动终止线程。
-
限时性,指可以判断某个线程在一定的时间段内能否获取锁,通过boolean tryLock(long time,TimeUnit unit),time表示时间数值,unit表示时间单位,返回值为boolean类型,true表示在该时间段内获取了锁,false表示在该时间段内没有获取锁。
高并发
并行和并发。
并发concurrency 并行parallelism
- 并行: 指多个操作同时执行,判断程序是否处于并行状态,就看 同一个时刻是否有一个以上的工作单元在运行,单线程是永远无法达到并行状态的。
- 并发: 指的是程序的结构,处理并行的能力。如果一个系统称之为并发系统,则表示该系统采用了支持并发的设计模式,所以并发并不是指多个线程同时执行,它指的是一种人为设计的程序结构,可以处理多线程的能力。
高并发是指我们设计的程序,可以支持海量的任务在同一时间段内同时执行。
高并发的标准:
-
QPS:每秒响应的http请求数量,QPS不等于并发量,并发数是指某时刻同时到到达服务器的请求数量。
-
吞吐量:单位时间内可以处理的请求数。
-
平均响应时间:系统对一个请求做出响应的平均时间。
QPS = 并发数/平均响应时间。
-
并发用户数量:系统在正常运行情况可以承载的用户数量。
提供系统并发能力的两种方式:1.垂直扩展,水平扩展。
垂直扩展
提升单机的处理能力。
-
增强单机硬件性能。
-
提升单机架构性能。
水平扩展
系统集群(分层架构,nginx反向代理分担web应用服务器的压力,数据层主从复制,读写分离,分表分库,减轻数据库服务器的压力)
重入锁 —— 可重入
package Test1;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
Account account = new Account();
new Thread(account,"普通用户").start();
new Thread(account,"超级用户").start();
}
}
class Account implements Runnable {
private int num;
private ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
// TODO Auto-generated method stub
reentrantLock.lock();
reentrantLock.lock(); //这里锁住几次,下面就要解锁几次
num++;
try {
Thread.currentThread().sleep(1000);
System.out.println(Thread.currentThread().getName() + "是第" + num + "位访问");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
reentrantLock.unlock();
reentrantLock.unlock();
}
}
}
返回上层目录
重入锁 —— 可中断
package Test1;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
StopLock stopLock = new StopLock();
Thread t1 = new Thread(stopLock,"线程1");
Thread t2 = new Thread(stopLock,"线程2");
t1.start();
t2.start();
try {
Thread.currentThread().sleep(1000);//此处线程休眠1s,如果线程2还不能拿到资源则中断。//此处也可改为停6s,看效果。
t2.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class StopLock implements Runnable{
private ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
// TODO Auto-generated method stub
try {
reentrantLock.lockInterruptibly();
System.out.println(Thread.currentThread().getName()+"get lock");
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
}
}
返回上层目录
重入锁 —— 限时性
package Test1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
TimeLock timeLock = new TimeLock();
new Thread(timeLock).start();
new Thread(timeLock).start();
}
}
class TimeLock implements Runnable{
private ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
// TODO Auto-generated method stub
try {
if(reentrantLock.tryLock(3, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName()+"get lock");
Thread.currentThread().sleep(5000);
}else {
System.out.println(Thread.currentThread().getName()+"not get lock");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(reentrantLock.isHeldByCurrentThread()) {
reentrantLock.unlock();
}
}
}
}