zoukankan      html  css  js  c++  java
  • synchronized 笔记

    1. 当一个线程正在访问一个对象的 synchronized 实例方法,那么其他线程不能访问该对象的其他 synchronized 方法

        对于每一个实例方法,锁是加在对象上的,一个线程访问其中一个 synchronized 修饰的实例方法时,这个线程就拿到了对象的锁,所以其他线程无法拿到该对象的锁,也就无法访问该对象的其他 synchronized 方法

    2. synchronized 修饰实例方法,两个(或多个)线程拿到同一个对象的锁,实现正确并发。

        一个简单的 +1 线程:

     1 class MyThread implements Runnable {
     2     static int i;
     3 
     4     public int getI() {
     5         return i;
     6     }
     7 
     8     public synchronized void incrI() {
     9         i++;
    10     }
    11 
    12     @Override
    13     public void run() {
    14         for (int j = 0; j < 1000000; j++) {
    15             incrI();
    16         }
    17     }
    18 }

        两个线程拿到同一个对象(myThread)的锁:

     1 public class SynTest {
     2     public static void main(String[] args) throws InterruptedException {
     3         MyThread myThread = new MyThread();
     4         Thread t1 = new Thread(myThread);
     5         Thread t2 = new Thread(myThread);
     6         t1.start();
     7         t2.start();
     8         t1.join();
     9         t2.join();
    10 
    11         System.out.println(MyThread.i);
    12     }
    13 }

    3. 当 synchronized 作用于静态方法时,其锁就是当前类的 class 对象锁。所以可以用两个不同的对象构造两个线程,但是这两个线程拿到的都是同一把锁(class 对象锁),所以仍然可以实现正确的并发。

    1 public synchronized static void incrI() {
    2     i++;
    3 }

       

     1 public class SynTest {
     2     public static void main(String[] args) throws InterruptedException {
     3         MyThread myThread = new MyThread();
     4         Thread t1 = new Thread(myThread);
     5         Thread t2 = new Thread(new MyThread());
     6         t1.start();
     7         t2.start();
     8         t1.join();
     9         t2.join();
    10 
    11         System.out.println(MyThread.i);
    12     }
    13 }

     4. synchronid 底层实现

        修饰代码块:monitorenter 和 monitorexit 指令。

        测试代码:

    1 public class SynBlock {
    2     private int i;
    3 
    4     public void incr() {
    5         synchronized (this) {
    6             i++;
    7         }
    8     }
    9 }

        javap 反编译之后:会有两个 exit,第一个是正常退出时执行,第二个是自动产生的,用于异常结束时执行

        

        修饰方法:使用 ACC_SYNCHRONIZED 标志

        

    5. synchronized 优化:偏向锁、轻量级锁

        偏向锁:同一个线程多次获取同一把锁时,无需申请,直接获取,有利于提高性能。适用于锁竞争不激烈的情况。

        轻量级锁:偏向锁失败之后,变为轻量级锁,适用于多个线程交替执行的情况,竞争少。

        自旋锁:会假设在不远的将来线程很快获得锁,让当前线程做空循环,如果可以获得锁,直接拿到,否则膨胀为重量级锁。

    6 . 可重入的含义:一个线程请求自己持有锁的资源,直接获取锁,无需再次申请。

    7. wait/notify/notifyAll 必须在 synchronized 中,因为这三个方法必须拿到 monitor 对象,而 synchronized 可以保证拿到 monitor 对象。

    参考:

    https://blog.csdn.net/javazejian/article/details/72828483

  • 相关阅读:
    Android 音视频开发(六): MediaCodec API 详解
    Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
    Android 音视频开发(四):使用 Camera API 采集视频数据
    Android 音视频开发(三):使用 AudioTrack 播放PCM音频
    Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件
    Android 音视频开发(一) : 通过三种方式绘制图片
    Android 使用View绘制文字(DrawText)技术总结
    Mac OS 中安装 autoconf 和 automake
    Android 自定义 View 绘制
    关于 Socket 设置 setSoTimeout 误用的说明
  • 原文地址:https://www.cnblogs.com/ainsliaea/p/11370018.html
Copyright © 2011-2022 走看看