4.2.3 Java锁相关-Synchronized

Synchronized 从使用到原理

Java中锁的概念

自旋锁: 是指当一个线程在获取锁的时候,如果锁已经被其他线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,知道获取到锁才会退出循环。(自旋锁就是通过CAS来不断的尝试获取执行AtomicInt/long等都是自旋锁的方式)

乐观锁:假定没有冲突,在修改数据时如果发现数据和之前获取的不一致,则读最新数据,修改后重试
悲观锁:假定会发生并发冲突,同步所有对数据的相关操作,从读数据就开始上锁。

独享锁(写):给资源加上写锁,线程可以修改资源,其他线程不能再加锁;(单写)
共享锁(读):给资源加上读锁后只能读不能改,其他线程也只能加读锁,不能加写锁(多读)

可重入锁、不可重入锁:线程拿到一把锁之后,可以自由进入同一把锁所同步的其他代码。


public class ReentrantLockDemo {

    private static int i = 0;

//    private final  static  Lock lc = new ReentrantLock(); //可重入锁

    private final static Lock lc = new KaneLock(); //不可重入锁


    public static void recursive() throws InterruptedException {
        lc.lock();//互斥的 ---针对于多线程
        i++;
        System.out.println("当前的值:" + i + ",调用的线程是:" + Thread.currentThread().getName());
        Thread.sleep(1000L);
        recursive();
        lc.unlock();
    }

    public static void main(String[] args) {
        try {
            Thread.currentThread().setName("aaaa");
            recursive();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}



public class KaneLock implements Lock {
    private boolean isLocked = false; //当前线程有没有被锁

    @Override
    public synchronized void lock() {
        while (isLocked) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isLocked = true;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public synchronized void unlock() {
        isLocked = false;
        this.notify();
    }

    @Override
    public Condition newCondition() {
        return null;
    }

}

公平锁、非公平锁:争抢锁的顺序,如果是按先来后到,则为公平

几种重要的锁实现方式: synchronized、ReentrantLock、ReentrantReadWriteLock.

同步关键字synchronized

  1. 用于实例方法、静态方法时,隐式指定锁对象
  2. 用于代码块时,显示指定锁对象
  3. 锁的作用域:对象锁、类锁、分布式锁
  4. 引申:如果时多个进程,怎么办 ?–不同的jvm之间需要借助第三方锁来实现了

特性:可重入、独享、悲观锁 、非公平
锁优化:锁消除(开启锁消除的参数:-XX:+DoEscapeAnalysis -XX:++EliminateLocks)
锁粗化 JDK做了锁粗化的优化,但我们自己可从代码层面优化。

public class SynchronizedDemo {

   public static void main(String[] args) {

       for (int i = 0; i < 10000; i++) {  //循环调用
           new SynchronizedDemo().test();
       }

   }


   public void test() {

       StringBuffer stringBuffer = new StringBuffer();
       //synchronized (this) {//JIT触发优化,被连续调用时产生锁消除 --因为本方法只被一个线程重复调用 不存在产生安全问题
           stringBuffer.append("a");
           stringBuffer.append("b");
           stringBuffer.append("c");

           stringBuffer.append("a");
           stringBuffer.append("b");
           stringBuffer.append("c");

           stringBuffer.append("a");
           stringBuffer.append("b");
           stringBuffer.append("c");
      // }

   }


   public void test1() {
       int i = 0;

       synchronized (this) {
           i++;
       }

       synchronized (this) {
           i--;
       }

       synchronized (this) {
           System.out.println("快速打印");
       }

       synchronized (this) {
           i++;
       }

       //jit会锁粗化优化
       synchronized (this) {
           i++;
           System.out.println("快速打印");
           i--;
           i++;
       }
   }


}

Note: synchronized 关键字,不仅实现同步,
JMM中规定,synchronized要保证可见性(不能够被缓存)

那么synchronized和volatile关键字的区别是什么呢:
synchronized保证了原子性和可见性 ,只能单个线程访问
volatile只保证可见性 不保证原子性,并且可让jit不做重排序,但可能多个线程同时访问
下面的这边文章讲的比较透彻请参考:
https://blog.csdn.net/li_w_ch/article/details/112483470

思考
在这里插入图片描述## 堆内存中的java对象
在这里插入图片描述

java对象头-Mark word

在这里插入图片描述

轻量级锁

在这里插入图片描述

重量级锁

在这里插入图片描述

偏向锁

在这里插入图片描述

锁的升级过程

在这里插入图片描述

对象头详解

在这里插入图片描述

https://zhuanlan.zhihu.com/p/138582291
下面这篇文章貌似讲的更为详细 可以参考
https://blog.csdn.net/tongdanping/article/details/79647337
这篇文章讲解了如何在cpu高的情况下找到对应的线程然后根据Jstack来查看问题
https://www.cnblogs.com/wuchanming/p/7766994.html

https://www.jianshu.com/p/9e02bed1387c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值