zoukankan      html  css  js  c++  java
  • 并发编程学习笔记(九、synchronize)

    目录:

    • synchronize作用
    • synchronize使用方式
    • synchronize导致的死锁
    • synchronize特性
    • synchronize原理

    synchronize作用

    并发场景限制共享资源的访问,使其只有一个线程可以执行某个方法或代码块,实现线程安全

    synchronize使用方式

    synchronize导致的死锁

    Thread1:lock A,waiting for B。

    Thread2:lock B,waiting for A。

    public class DeadLock {
    
        /**
         * A锁
         */
        private static String A = "A";
    
        /**
         * B锁
         */
        private static String B = "B";
    
        public static void main(String[] args) {
            new DeadLock().deadLock();
        }
    
        public void deadLock() {
            // 先获取A锁再获取B锁
            Thread t1 = new Thread(() -> {
                synchronized (A) {
                    try {
                        // 获取A锁后休眠2s
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B) {
                        // 获取B锁
                        System.out.println("thread1...");
                    }
                }
            });
    
            // 先获取B锁再获取A锁
            Thread t2 = new Thread(() -> {
                synchronized (B) {
                    try {
                        // 获取B锁后休眠2s
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (A) {
                        System.out.println("thread2...");
                    }
                }
            });
    
            t1.start();
            t2.start();
        }
    }

    synchronize特性

    1、原子性:线程互斥的访问同步代码。

    2、可见性:保证共享变量的修改能及时可见。

    • 对一个变量unlock时,必须要将其同步到主内存中。
    • 对一个变量lock时,会清空工作内存中此变量的值。
    • 在执行引擎使用此变量前,需要重新从主内存中执行load或assign操作,以初始化变量值。

    3、有序性:有效解决重排序问题,即一个unlock操作先行发生与lock操作。

    synchronize可以把任何非null的对象作为锁,在Host JVM中锁叫做对象监视器。

    synchronize原理

    当一个线程访问同步代码块的时候,首先需要获取锁才能执行,当退出或抛出异常时需要释放锁。

    那么它是如何来实现这一机制的呢,来看看如下代码:

    public class SynchronizedDemo {
        public void method() {
            synchronized (this) {
                System.out.println("Method 1 start");
            }
        }
    }

    monitorenter:监视器锁(monitor),当monitor被占用时便是锁定状态,执行monitorenter会尝试获取monitor的所有权。过程如下:

    • monitor进入数为0,则该线程进入monitor,进入数为1,则该线程为monitor的所有者。
    • 若该线程已拥有monitor,只是重新进入的话,monitor加1。
    • 如果其它线程占用monitor,则该线程阻塞,直到进入数为0,该线程重新尝试获取monitor的所有权。

    monitorexit:执行monitorexit的必须是monitor的拥有者。

    • 执行此操作,monitor的进入数减1,若减1后进入数为0,则线程退出monitor。

    ———————————————————————————————————————————————————————

    通过上述的示例便可以很清楚的了解到synchronize是如何实现的了,通过monitor对象来实现的。

    其实wait、notify方法也依赖于monitor对象,这也就是为什么wait、notify方法必须要在synchronize中才能调用的原因了。

  • 相关阅读:
    Matplotlib API汉化 Pyplot API
    Pycharm2018的激活方法或破解方法
    优化器
    泛化能力,欠拟合,过拟合,不收敛和奥卡姆剃刀原则
    sas9.2 windows7系统 10年11月后 建立永久数据集时,提示:“用户没有与逻辑库相应的授权级别
    Json、JavaBean、Map、XML之间的互转
    19年博文
    Java demo之时间
    idea相关
    shell脚本
  • 原文地址:https://www.cnblogs.com/bzfsdr/p/12499742.html
Copyright © 2011-2022 走看看