并发操作之——synchronized

并发操作

并发操作之——synchronized


并发操作之——synchronized

  • 并发操作
  • 一、sychronized
    • 1、方法加锁:
    • 2、代码块加锁:
  • 二、JDK1.6后的优化部分
    • 1、JVM对象在内存中的组成
    • 2、对象头模型


一、sychronized

synchronized是解决线程安全的问题,常用在 同步普通方法、静态方法、代码块 中

非公平、可重入

每个对象有一个锁和一个等待队列,锁只能被一个线程持有,其他需要锁的线程需要阻塞等待。锁被释放后,对象会从队列中取出一个并唤醒,唤醒哪个线程是不确定的,不保证公平性

两种形式:

1、方法加锁:

生成的字节码文件中会多一个 ACC_SYNCHRONIZED 标志位,当一个线程访问方法时,会去检查是否存在ACC_SYNCHRONIZED标识,如果存在,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象,也叫隐式同步

package net.xdclass.xdclasssp.syn;

/**
 * @author Cym
 * @date 2021/9/8
 */
public class synchronizedDemo {

    private static final String lockA = "aa";

    private synchronized void test1() {
        System.out.println(123);
    }


}

2、代码块加锁:

加了 synchronized 关键字的代码段,生成的字节码文件会多出 monitorenter 和 monitorexit 两条指令,每个monitor维护着一个记录着拥有次数的计数器, 未被拥有的monitor的该计数器为0,当一个线程获执行monitorenter后,该计数器自增1;当同一个线程执行monitorexit指令的时候,计数器再自减1。当计数器为0的时候,monitor将被释放.也叫显式同步

两种本质上没有区别,底层都是通过monitor来实现同步, 只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成

package net.xdclass.xdclasssp.syn;

/**
 * @author Cym
 * @date 2021/9/8
 */
public class synchronizedDemo {

    private static final String lockA = "aa";

    private synchronized void test1() {
        System.out.println(123);
    }

    private void test2() {

        synchronized (lockA) {
            System.out.println(123);
        }

    }
}

二、JDK1.6后的优化部分

有得到锁的资源进入Block状态,涉及到操作系统用户模式和内核模式的切换,代价比较高
jdk6进行了优化,增加了从偏向锁到轻量级锁再到重量级锁的过渡,但是在最终转变为重量级锁之后,性能仍然较低

1、JVM对象在内存中的组成

并发操作之——synchronized_第1张图片

2、对象头模型

并发操作之——synchronized_第2张图片

你可能感兴趣的:(并发,面试,java,synchronized,并发,jvm)