最后
由于细节内容实在太多了,为了不影响文章的观赏性,只截出了一部分知识点大致的介绍一下,每个小节点里面都有更细化的内容!
小编准备了一份Java进阶学习路线图(Xmind)以及来年金三银四必备的一份《Java面试必备指南》
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + “\t come in 😊”);
while (!atomicReference.compareAndSet(null,thread)){
}
}
public void myUnLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread,null);
System.out.println(thread.getName() + “\t invoked myUnLock”);
}
public static void main(String[] args) throws InterruptedException {
SpinLockDemo spinLockDemo = new SpinLockDemo();
new Thread(() -> {
spinLockDemo.myLock();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLockDemo.myUnLock();
},“A”).start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
spinLockDemo.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLockDemo.myUnLock();
},“B”).start();
}
}
可重入锁(又名递归锁)
可重入锁的概念
可重入锁(也叫做递归锁)
指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。也就是说,线程可以进入任何一个它已经拥有的锁所同步着的代码快。
ReentrantLock / Synchronized 就是一个典型的可重入锁
可重入锁的最大作用是避免死锁
Demo2# 可重入锁
package com.nuih.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class MyPhone implements Runnable {
public synchronized void sendMsg(){
System.out.println(Thread.currentThread().getName() + “\t invoked sendMsg”);
sendEmail();
}
public synchronized void sendEmail(){
System.out.println(Thread.currentThread().getName() + “\t##### invoked sendEmail”);
}
Lock lock = new ReentrantLock();
@Override
public void run() {
get();
}
public void get(){
lock.lock();
try{
System.out.println(Thread.currentThread().getName() + “\t invoked get”);
set();
}finally {
lock.unlock();
}
}
public void set(){
lock.lock();
try{
System.out.println(Thread.currentThread().getName() + “\t###### invoked set”);
}finally {
lock.unlock();
}
}
}
/**
- 可重入锁(也叫做递归锁)
- 指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,
- 在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
- 也就是说,线程可以进入任何一个它已经拥有的锁所同步着的代码快。
- t1 invoked sendMsg() t1线程在外层方法获取锁的时候
- t1 ##### invoked sendEmail t1在进入内层方法会自动获取锁
- t2 invoked sendMsg()
- t2 ##### invoked sendEmail
- @author: hejianhui
- @create: 2020-06-21 14:10
- @see ReentrantLockDemo
- @since JDK1.8
*/
public class ReentrantLockDemo {
public static void main(String[] args) throws InterruptedException {
MyPhone myPhone = new MyPhone();
new Thread(() -> {
myPhone.sendMsg();
},“t1”).start();
new Thread(() -> {
myPhone.sendMsg();
},“t2”).start();
TimeUnit.SECONDS.sleep(1);
System.out.println(“\n\n\n\n”);
Thread t3 = new Thread(myPhone,“t3”);
t3.start();
Thread t4 = new Thread(myPhone,“t4”);
t4.start();
}
}
独占锁(写锁)/共享锁(写锁)/互斥锁
是什么?
独占锁:指该锁一次只能被一个线程所持有。对ReentrantLock和Synchronized而言都是独占锁
共享锁:指该锁可被多个线程所持有。
对ReentrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是非常高效的,读写、写读、写写的过程是互斥的。
Demo#3 独占锁/共享锁
package com.nuih.lock;
import com.nuih.map.HashMap;
import com.nuih.map.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class MyCache{
private volatile Map<String,Object> map = new HashMap<>();
final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void put(String key,Object value){
readWriteLock.writeLock().lock();
try{
System.out.println(Thread.currentThread().getName() + “\t 开始写入:” + key);
map.put(key,value);
System.out.println(Thread.currentThread().getName() + “\t 写入完成”);
}finally {
readWriteLock.writeLock().unlock();
}
}
public void get(String key){
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + “\t 开始读取”);
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + “\t 读物完成:” + result);
}finally {
readWriteLock.readLock().unlock();
}
}
}
/**
- 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
- 但是
- 如果又一个线程想去写共享资源了,就不应该再有其它线程可以对该资源进行读或写
- 小总结:
-
读-读可以共存
-
读-写不能共存
-
写-写不能共存
-
写操作:原子+独占,中间过程必须一个完整的统一体,中间不许被分割
- @author: hejianhui
- @create: 2020-06-21 15:39
- @see ReadWriteLockDemo
- @since JDK1.8
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for(int i=0;i<5;i++){
int finalI = i;
new Thread(() -> {
myCache.put(finalI+“”,finalI);
},“A”+String.valueOf(i)).start();
}
for(int i=0;i<5;i++){
int finalI = i;
new Thread(() -> {
myCache.get(finalI+“”);
},“B”+String.valueOf(i)).start();
}
}
}
最后
大家看完有什么不懂的可以在下方留言讨论.
谢谢你的观看。
觉得文章对你有帮助的话记得关注我点个赞支持一下!
作者:一角钱
链接:https://juejin.im/post/6870484893295050759
总结
上述知识点,囊括了目前互联网企业的主流应用技术以及能让你成为“香饽饽”的高级架构知识,每个笔记里面几乎都带有实战内容。
很多人担心学了容易忘,这里教你一个方法,那就是重复学习。
打个比方,假如你正在学习 spring 注解,突然发现了一个注解@Aspect,不知道干什么用的,你可能会去查看源码或者通过博客学习,花了半小时终于弄懂了,下次又看到@Aspect 了,你有点郁闷了,上次好像在哪哪哪学习,你快速打开网页花了五分钟又学会了。
从半小时和五分钟的对比中可以发现多学一次就离真正掌握知识又近了一步。
人的本性就是容易遗忘,只有不断加深印象、重复学习才能真正掌握,所以很多书我都是推荐大家多看几遍。哪有那么多天才,他只是比你多看了几遍书。
易遗忘,只有不断加深印象、重复学习才能真正掌握,所以很多书我都是推荐大家多看几遍。哪有那么多天才,他只是比你多看了几遍书。