JVM在运行时,会将其管理的内存区域划分为方法区、堆、虚拟机栈、本地方法栈和程序计数器5个区域;
JMM用于定义程序汇总变量的访问规则,即在JVM中如何将变量存储到内存,以及如何从内存中获取变量(此处变量指所有线程共享的变量)。
与JVM内存区域不同,JMM是从另一个角度对内存进行划分,分为主内存和工作内存。
JMM规定所有的变量都存储在主内存中,每个线程还拥有自己独立的工作内存。主内存中的变量会通过复制的方式留给线程的工作内存一个副本,供各个线程独立使用。 线程对变量的所有读写操作都是在工作内存中进行的,工作内存中的副本变量会通过JMM与主内存中的原变量保持同步。
多个线程在争夺同一个资源时,为了让这些线程协同工作、提高CPU利用率,可以让线程之间进行沟通,具体可以通过wait()和notify()实现。
使用时需要注意几点:
tryLock的意思是,当一个线程尝试加锁失败后,会再次请求,持续一段时间,如果一直失败则放弃加锁。
package com.guor.demo.thread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TryLockTest extends Thread{
Lock lock = new ReentrantLock();
@Override
public void run() {
// 获取线程名称
String threadName = Thread.currentThread().getName();
boolean isLocked = false;
try {
// 在2秒内尝试加锁
isLocked = lock.tryLock(2, TimeUnit.SECONDS);
// 加锁成功
if(isLocked){
Thread.sleep(1000);
System.out.println(threadName+"加锁成功");
}else {
System.out.println(threadName+"加锁失败");
}
} catch (InterruptedException e) {
System.out.println(threadName+"tryLock 异常:"+e);
}finally {
if(isLocked){
lock.unlock();
System.out.println(threadName+"解锁");
}
}
}
public static void main(String[] args) {
TryLockTest thread1 = new TryLockTest();
TryLockTest thread2 = new TryLockTest();
thread1.setName("线程1");
thread2.setName("线程2");
thread1.start();
thread2.start();
}
}
在AQS中维护着一个表示共享资源加锁情况的变量 volatile int state,以及一个FIFO的线程阻塞队列(称为CLH队列)。当多个线程并发访问共享资源时,如果共享资源已经被某个线程加了锁,那么其它线程在访问此共享资源时就会加入CLH队列。
当state的值为1时,就表示共享资源被某个线程加了一次锁;
当state的值为0时,表示共享资源没有被加锁,随时可以访问;
例如ReentrantLock的state初始值为0,当某个线程调用lock()方法时,lock()就会在底层触发tryAcquire(1),把该资源的state修改为1,表示该资源加了一把锁,之后就可以独占使用该资源,之后再调用lock()就会失败并进入阻塞状态(因为ReentrantLock是独占方式,同一时间只能被一个线程加锁),只有在该线程调用哪个unlock()的时候,会在底层触发tryRelease(1)将state的值变为0,也就是释放锁。
(1)int tryAcquireShared(int arg)
(2)tryReleaseShared(int arg)
尝试释放该资源的arg个锁。
CountDownLatch的构造方法CountDownLatch(int count)可以将state的初始值设置为count,并交给count个线程去并发执行,于此同时,主线程进入阻塞状态。当每个子线程执行完毕后,都会调用一次countDown(),countDown()会在底层调用tryReleaseShared(1),即把state减1。
因此,当所有子线程全部执行完毕后,state的值就会变为0,此时唤醒主线程,从而实现了闭锁功能。
Java高并发编程实战1,那些年学过的锁
Java高并发编程实战2,原子性、可见性、有序性,傻傻分不清
Java高并发编程实战3,Java内存模型与Java对象结构
Java高并发编程实战4,synchronized与Lock底层原理
Java高并发编程实战5,异步注解@Async自定义线程池
Java学习路线总结,搬砖工逆袭Java架构师
10万字208道Java经典面试题总结(附答案)
SQL性能优化的21个小技巧
Java基础教程系列
Spring Boot 进阶实战