synchronized 分析

并发问题的出现

public class SynchronizedTest extends Thread{
    private static int index = 1;
    private static final int MAX=50;
    @Override
    public void run() {
        while (index <= MAX) {
            System.out.println(Thread.currentThread().getName()+"得到数字:"+(index++));
        }
    }

    public static void main(String[] args) {
        SynchronizedTest test1 = new SynchronizedTest();
        SynchronizedTest test2 = new SynchronizedTest();
        SynchronizedTest test3 = new SynchronizedTest();
        SynchronizedTest test4 = new SynchronizedTest();
        SynchronizedTest test5 = new SynchronizedTest();
        test1.start();
        test2.start();
        test3.start();
        test4.start();
        test5.start();
    }
}

这是一个典型的案列,上面可能会出现多种并发的错误,例如 跳号 重号或者超过最大值
可以使用synchronized来解决并发的问题

synchronized概念

  1. 原理:使用锁的机制来实现同步

锁机制的特性:
1.互斥性:即在同一时间只允许一个线程持有某个对象锁
2.可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的

synchronized用法

  1. 同步方法

     (1)同步非静态方法
     
     	Public synchronized void methodName(){
     	……
     	}
     (2)同步静态方法
     	Public synchronized static void methodName(){
     	……
     	}
    
  2. 同步代码块

     synchronized(this|object) {}
     synchronized(类.class) {}
    

synchronized原理分析

  1. 线程堆栈分析

jconsole
在这里插入图片描述
jstack pid
在这里插入图片描述

  1. JVM指令分析(javap -V 反编译)

      public void run();
     descriptor: ()V
     flags: ACC_PUBLIC
     Code:
       stack=3, locals=4, args_size=1
          0: aload_0
          1: dup
          2: astore_1
          3: monitorenter		锁的入口
          4: getstatic     #2                  // Field index:I
          7: sipush        500
         10: if_icmpgt     77
         13: getstatic     #4                  // Field java/util/concurrent/TimeUnit.SECONDS:Ljava/util/concurrent/TimeUnit;
         16: ldc2_w        #5                  // long 3l
         19: invokevirtual #7                  // Method java/util/concurrent/TimeUnit.sleep:(J)V
         22: goto          30
         25: astore_2
         26: aload_2
         27: invokevirtual #9                  // Method java/lang/InterruptedException.printStackTrace:()V
         30: getstatic     #2                  // Field index:I
         33: iconst_1
         34: iadd
         35: putstatic     #2                  // Field index:I
         38: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
         41: new           #11                 // class java/lang/StringBuilder
         44: dup
         45: invokespecial #12                 // Method java/lang/StringBuilder."<init>":()V
         48: invokestatic  #13                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
         51: invokevirtual #14                 // Method java/lang/Thread.getName:()Ljava/lang/String;
         54: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
         57: ldc           #16                 // String 得到数字:
         59: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
         62: getstatic     #2                  // Field index:I
         65: invokevirtual #17                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
         68: invokevirtual #18                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
         71: invokevirtual #19                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         74: goto          4
         77: aload_1
         78: monitorexit			锁的出口
         79: goto          87
         82: astore_3
         83: aload_1
         84: monitorexit
         85: aload_3
         86: athrow
         87: return  
    

原理:monitor一个线程占有,其他线程请求时会进入BOLCK,直到monitor为0,触发Monitorexit

3.使用synchronized注意的问题

与moniter关联的对象不能为空
synchronized的作用域不能太大
不同的monitor企图锁相同的方法
注意多个锁的交叉,异能会导致死锁

JVM对synchronized的优化

1.锁的进化

偏向锁:在对象第一次被某一线程占有的时候,锁标记01,写入线程号。
轻量级锁:线程有交替使用的时候,互斥性一般 当偏向锁CAS失败 锁标记为00,升级为轻量级锁
重量级锁: 当等待时间长,强互斥,锁标记为10
自旋锁:竞争失败的时候,不是马上转化级别,而是执行几次空循环5 10
锁消除:JIT(即时编译器)在编译的时候吧不必要的锁去掉

2.一个对象包含的信息
在这里插入图片描述

对象头和monitor(加锁的基础)
1.32/64bit的hashcode
实例变量
1.私有的变量
填充数据
1.对象的起始地址(8字节)
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值