0
点赞
收藏
分享

微信扫一扫

Synchronized关键字原理


(Android多线程:这是一份全面&详细的Synchronized学习指南

synchronized常用的使用方式

  • 修饰代码块,即同步语句块,其作用的范围是大括号{}扩区来的代码
  • 修饰普通方法,即同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象
  • 修饰静态方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象

使用规则

  1. 锁对象设置
    a。修饰代码块时,需1个reference对象, 作为锁的对象

// 修饰代码块
    public void synMethod(Object a1) {
        synchronized (a1) { // 需要一个实例

        }
    }

b。修饰实例方法时,默认的锁对象 = 当前对象

// 修饰实例方法
    public synchronized void increase1() {
        //i++;
    }

c。修饰类方法(静态)时,默认的锁对象 = 当前类的Class对象

// 修饰静态方法
    public static synchronized void increase2() {
        //i++;
    }

  1. 根据锁对象的不同,一把锁同时最多只能被一个线程持有
  • 若目标锁已被当前线程持有,其它线程只能阻塞等待当前线程释放目标锁
  • 若当前线程已持有目标锁,其它线程仍然可以调用目标类中无被synchronized修饰的方法
  1. 当对象获取多个锁时,必须以相反的顺序释放&在锁哦有锁被获取时相同的词法范围内释放所有锁
  • 若线程进入由线程已拥有的监控器保护的synchronized块,就允许线程继续进行
  • 只有线程推出它进入的监控器保护的第一个synchronized块时,才释放锁
  1. 特别注意
  • Java类中,实例对象会有多个,但只有1个Class对象
    即 类的不同实例 共享该类的Class对象
    实际上,Class对象也属于Java对象, 只是有点儿特殊
  • 静态方法&实例方法上的锁默认不一样
    若同步则需指定两把锁
    静态方法加锁,能和所有其他静态方法加锁的 进行互斥
    直接属于类,效果同xx.class锁

特点

  • 原子性
    一个操作 / 一系列操作
    (要么全部执行/全部执行)
    (数据库中的“事物” = 典型的原子操作)
  • 可见性
    当一个线程修改了共享属性的值后,其它线程能立刻看到共享属性值的更改
    (JMM的内存空间分为:主存&工作内存 :变量存于主存中;线程使用的是自身工作内存,更新后再同步到主存)
    (共享属性的修改过程;从主存中读取&复制到工作内存中,在工作内存中修改完成后,再同步到主存、从而刷新主存中的值)
    (若线程A在工作内存中修改完成单还未刷新主存中的值,线程B看到的值还是旧值。此时,可见性就无法保证)
  • 有序性
    程序的运行顺序看起来和我们编写逻辑的顺序一致,单计算机在实际执行中却并不一定
    (为了提高性能,编译器&处理器都会对代码进行重新排序)
    (但有个前提:重新排序的结果和单线程执行程序顺序一致)

Synchronized 和 ReenTrantLock的对比

  1. 两者都是可重入锁
  2. synchronized依赖于JVM而ReenTrantLock依赖于API
  3. ReenTrantLock比synchronized增加了一些高级功能
    ReenTrantLock多了三点:1. 等待可中断 2. 可实现公平锁 3. 可实现选择性通知
  4. 性能已不是选择标准

synchronized与ThreadLocal的对比

  1. synchronized关键字主要解决多线程共享数据同步问题;ThreadLocal主要解决多线程中数据因并发产生不一致问题。
  2. synchrozined关键字是利用锁的机制,使变量或代码块只能 被一个线程访问。而ThreadLocal为每一个线程都提供变量的副本,使得每个线程访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。

ReentrantLock原理

使用

public static void main(String[] args) {
    Lock lock = new ReentrantLock();
    lock.lock();
    try {
        System.out.println("Hello World!!");
    } finally {
        lock.unlock();
    }
}

AQS

Synchronized关键字原理_静态方法

  • 非公平锁:如果同时还有另一个线程进来尝试获取,那么有可能会让这个线程抢先获取
  • 公平锁:如果同时还有另一个线程进来尝试获取,当它发现自己不是在队首的话,就会排到队尾,由队尾的线程获取到锁

NonfairSync

  • 第一步。尝试去获取锁。如果尝试获取锁成功,方法直接返回。
  • 第二步。入队。
  • 第三部。挂起。



举报

相关推荐

0 条评论