zoukankan      html  css  js  c++  java
  • Java高并发之魂:synchronized深度解析

    第一章Synchronzied简介

    1、作用

    官方介绍

    翻译:同步方法支持一种简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的

    一句话说出Synchronized的作用:能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果

    2、地位

    • Synchronized是Java的关键字,被Java语言原生支持
    • 是最基本的互斥同步手段
    • 是并发编程中的元老级角色,是并发编程的必学内容

    3、不使用并发手段的后果演示

    代码实战:两个线程同时a++,最后结果会比预计的少

    public class DisappearRequest1 implements Runnable {
    
        static DisappearRequest1 instance = new DisappearRequest1();
    
        static int i=0;
    
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(instance);
            Thread t2 = new Thread(instance);
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println(i);  //运行结果总是小于200000
        }
    
        @Override
        public void run() {
            for (int j=0; j<100000; j++){
                i++;
            }
        }
    }

    原因:count++,它看上去只是一个操作,实际上包含了三个动作:

    1、读取count

    2、将count加一

    3、将count的值写入到内存中

    第二章Synchronized的两种用法

    1、对象锁

    包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(this或自己指定锁对象)

    1⃣️代码块形式:

    this

    public class SynchronizedObjectCodeBlock2 implements Runnable {
    
        static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
    
        @Override
        public void run() {
            synchronized (this){
                System.out.println("我是对象锁的代码块形式。我叫" + Thread.currentThread().getName());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "运行结束。");
            }
        }
    
        public static void main(String[] args) {
            Thread t1 = new Thread(instance);
            Thread t2 = new Thread(instance);
            t1.start();
            t2.start();
            while (t1.isAlive() || t2.isAlive()){
    
            }
            System.out.println("finished");
        }
    }

    手动指定锁对象

    不同锁对象

    public class SynchronizedObjectCodeBlock2 implements Runnable {
    
        static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
    
        Object lock1 = new Object();
        Object lock2 = new Object();
    
        @Override
        public void run() {
            synchronized (lock1){
                System.out.println("我是lock1。我叫" + Thread.currentThread().getName());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "lock1部分运行结束。");
            }
    
            synchronized (lock2){
                System.out.println("我是lock2。我叫" + Thread.currentThread().getName());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "lock2部分运行结束。");
            }
        }
    
        public static void main(String[] args) {
            Thread t1 = new Thread(instance);
            Thread t2 = new Thread(instance);
            t1.start();
            t2.start();
            while (t1.isAlive() || t2.isAlive()){
    
            }
            System.out.println("finished");
        }
    }

    相同锁对象

    public class SynchronizedObjectCodeBlock2 implements Runnable {
    
        static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
    
        Object lock1 = new Object();
        Object lock2 = new Object();
    
        @Override
        public void run() {
            synchronized (lock1){
                System.out.println("我是lock1。我叫" + Thread.currentThread().getName());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "lock1部分运行结束。");
            }
    
           synchronized (lock1){
                System.out.println("我是lock2。我叫" + Thread.currentThread().getName());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "lock2部分运行结束。");
            }
        }
    
        public static void main(String[] args) {
            Thread t1 = new Thread(instance);
            Thread t2 = new Thread(instance);
            t1.start();
            t2.start();
            while (t1.isAlive() || t2.isAlive()){
    
            }
            System.out.println("finished");
        }
    }

    2⃣️方法锁形式:synchronized修饰普通方法,锁对象默认为this

    public class SynchronizedObjectMethod3 implements Runnable {
    
        static SynchronizedObjectMethod3 instance = new SynchronizedObjectMethod3();
    
        public static void main(String[] args) {
            Thread t1 = new Thread(instance);
            Thread t2 = new Thread(instance);
            t1.start();
            t2.start();
            while (t1.isAlive() || t2.isAlive()){
    
            }
            System.out.println("finished");
        }
    
        @Override
        public void run() {
            method();
        }
    
        public synchronized void method(){
            System.out.println("我的对象锁的方法修饰符形式,我叫" + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "运行结束");
        }
    }

    2、类锁

    指synchronized修饰静态的方法或指定锁为Class对象

  • 相关阅读:
    第0次作业
    第4次作业
    第3次作业
    第2次作业
    C#浮点数保留位数
    第0次作业
    软件工程第4次作业
    软件工程第3次作业
    软件工程第2次作业
    软件工程第1次作业
  • 原文地址:https://www.cnblogs.com/yanguobin/p/12096279.html
Copyright © 2011-2022 走看看