各种锁的理解
公平锁、非公平锁
公平锁:先到先得(不可插队)
非公平锁:达者为先(可插队)---------->默认- public ReentrantLock() {
- //默认非公平锁
- sync = new NonfairSync();
- }
复制代码- //重载的构造方法,通过fair控制是否公平
- public ReentrantLock(boolean fair) {
- sync = fair ? new FairSync() : new NonfairSync();
- }
复制代码 可重入锁(递归锁)
所有的锁都是可重入锁

Synchronized版
- package org.example.lock;
- public class Demo01 {
- public static void main(String[] args) {
- phone1 p1 = new phone1();
- new Thread(()->{
- p1.ems();
- },"A").start();
- new Thread(()->{
- p1.ems();
- },"B").start();
- }
- }
- class phone1{
- public synchronized void ems(){
- System.out.println(Thread.currentThread().getName()+"---------->ems");
- call();
- }
- public synchronized void call(){
- System.out.println(Thread.currentThread().getName()+"---------->call");
- }
- }
复制代码 ems方法中包含了call方法,所以当我们调用ems方法获取到锁时,也把call方法的synchronized锁获取到了。
错误理论
- 当线程A运行ems方法后运行call方法时ems锁释放,线程B可以获取到ems方法
正确理论
- 当线程A运行ems方法后运行call方法时ems方法的锁还未释放时就拿到了call方法中的锁,当call方法的锁释放后ems方法的锁才会释放。线程B此时就可以运行ems方法了
Lock版
- package org.example.lock;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class Demo02 {
- public static void main(String[] args) {
- phone2 p2 = new phone2();
- new Thread(()->{
- p2.ems();
- },"A").start();
- new Thread(()->{
- p2.ems();
- },"B").start();
- }
- }
- class phone2{
- Lock lock = new ReentrantLock();
- public void ems(){
- lock.lock();
- try {
- System.out.println(Thread.currentThread().getName()+"---------->ems");
- call();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- //等待call方法锁解锁后再解锁
- lock.unlock();
- }
- }
- public void call(){
- lock.lock();
- try {
- System.out.println(Thread.currentThread().getName()+"---------->call");
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- lock.unlock();
- }
- }
- }
复制代码 自旋锁
spinlock(不断尝试直至成功)
已经见过了,就是unsafe中的自增getAndAddInt方法中的do-while循环就是一把自旋锁

自己写一把锁- package org.example.lock;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.atomic.AtomicReference;
- public class SpinLockDemo {
- //int 0
- //Thread null
- public static AtomicReference<Thread> atomic = new AtomicReference<>();
- public static void lock(){
- Thread thread = Thread.currentThread();
- System.out.println("===============>"+thread.getName()+"===========>lock");
- //自旋锁,若线程等于null,则compareAndSet为true,加!就为false,就会一直循环
- while (!atomic.compareAndSet(null,thread)){
- }
- }
- public static void unlock(){
- Thread thread = Thread.currentThread();
- System.out.println("===============>"+thread.getName()+"===========>unlock");
- //自旋锁
- atomic.compareAndSet(thread,null);
- }
- public static void main(String[] args) throws InterruptedException {
- new Thread(()->{
- try {
- lock();
- TimeUnit.SECONDS.sleep(10);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- unlock();
- }
- },"A").start();
- TimeUnit.SECONDS.sleep(1);
- new Thread(()->{
- try {
- lock();
- TimeUnit.SECONDS.sleep(2);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- unlock();
- }
- },"B").start();
- }
- }
复制代码 死锁
死锁是什么

死锁测试- package org.example.lock;
- import java.util.concurrent.TimeUnit;
- public class DeadLockDemo {
- public static void main(String[] args) {
- String a = "A";
- String b = "B";
- new Thread(()->{new MyThread(a, b).run();},"A").start();
- new Thread(()->{new MyThread(b, a).run();},"B").start();
- }
- }
- class MyThread implements Runnable{
- private String lockA;
- private String lockB;
- public MyThread(String lockA, String lockB) {
- this.lockA = lockA;
- this.lockB = lockB;
- }
- @Override
- public void run() {
- synchronized (lockA){
- System.out.println(Thread.currentThread().getName()+"lock:"+lockA+"=>get"+lockB);
- try {
- TimeUnit.SECONDS.sleep(2);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- synchronized (lockB){
- System.out.println(Thread.currentThread().getName()+"lock:"+lockB+"=>get"+lockA);
- }
- }
- }
- }
复制代码程序突然卡住死锁如何排查?
1、使用jps-l定位进程号

查看当前java活着的进程
2、使用jstack 进程号查看死锁问题


查找到一个死锁问题!
面试或者工作中排查问题:
1、查看异常
2、查看日志
3、查看堆栈信息
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |