一、synchronized概述基本使用
为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题。
synchronized结论:
1、java5.0之前,协调线程间对共享对象的访问的机制只有synchronized和volatile,但是内置锁在功能上存在一些局限性,jdk5增加了Lock以及ReentrantLock。
2、java5.0,增加了一种新的机制:显式锁ReentrantLock,注意它并不是替代内置锁synchronized的机制,而是当内置锁不适用时,作为一种可选的高级功能。
3、jdk6之后,synchronized与java.util.concurrent包中的ReentrantLock相比,由于JDK1.6中加入了针对锁的优化措施,使得synchronized与ReentrantLock的性能基本持平。ReentrantLock只是提供了synchronized更丰富的功能,而不一定有更优的性能,所以在synchronized能实现需求的情况下,优先考虑使用synchronized来进行同步。
synchronized在JDK5之前一直被称为重量级锁,底层是使用操作系统的mutex lock实现的,是一个较为鸡肋的设计,而在JDK6对synchronized内在机制进行了大量显著的优化,加入了CAS,轻量级锁和偏向锁的功能,性能上已经跟ReentrantLock相差无几,而且synchronized在使用上更加简单,不易出错(避免哲学家就餐问题造成的死锁),因此如果仅仅是为了实现互斥,而不需要使用基于Lock的附加属性(中断、条件等),推荐优先使用synchronized。
1、synchronized的几种加锁方式以及基础说明
| 修饰内容 | 锁类型 | 示例 |
|---|---|---|
| 没加锁 | 没加锁 | 示例1 |
| 修饰代码块 | 任意对象锁 | 示例2 |
| 修饰普通方法 | this锁 | 示例3 |
| 修饰静态方法 | 类锁 | 示例4 |
1.1、示例以及说明
示例1、没有synchronized加锁
public class NoSynchronizedDemo { public void method() { System.out.println("Method 1 start"); } }
查看核心字节码
public void method(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Method 1 start 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 5: 0 line 6: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 this Lcom/lhx/cloud/javathread/NoSynchronizedDemo;