• Java基础 --- 线程同步 synchronized关键字


    synchronized 关键字

    • Lock and Condition interface给了程序员很高的自由度来控制锁, 但是通常不需要这么高的自由度
    • Java提供一套更简便的机制来加锁 ---- synchronized 关键字 和 intrinsic lock
    • Java 1.0之后, 每个object类都有一个 intrinsic lock, 每个object类都有wiat和notifyAll方法

    synchronized

    • 当一个方法使用synchronized修饰时, 锁会保护整个方法
    • 也就是如果要执行这个方法, 线程必须拿到intrinsic object lock.

    使用synchronized重写transfer方法:

    class Bank
    {
    	 private double[] accounts;
    	 public synchronized void transfer(int from, int to, int amount) throws InterruptedException {
    		 while (accounts[from] < amount)
    			wait(); // wait on intrinsic object lock's single condition
    		 accounts[from] -= amount;
    		 accounts[to] += amount;
    		 notifyAll(); // notify all threads waiting on the condition
    	 }
    	 public synchronized double getTotalBalance() { . . . }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    The intrinsic locks and conditions have some limitations. Among them:

    • You cannot interrupt a thread that is trying to acquire a lock.
    • You cannot specify a timeout when trying to acquire a lock.
    • Having a single condition per lock can be inefficient

    synchronized 关键字修饰静态方法

    • synchronized 关键字可以修饰静态方法, 也就是对 类 加锁, 也叫做类锁
    public class Car {
    
        public static synchronized void staticRuning1(Thread thread){
            System.out.println(thread.getName()+ " static car1 得到锁");
            System.out.println("------ static car1 is running ------");
            working();
            System.out.println(thread.getName()+ " static car1 释放锁");
            System.out.println();
        }
        public static synchronized void staticRuning2(Thread thread){
            System.out.println(thread.getName()+ " static car2 得到锁");
            System.out.println("------ static car2 is running ------");
            working();
            System.out.println(thread.getName()+ " static car2 释放锁");
            System.out.println();
        }
    
    	public static void  working(){
            try{
                Thread.sleep(1000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    public class test02 {
        public static void main(String[] args) {
    
            //线程1 类
            Thread t1 = new Thread(){
                @Override
                public void run() {
                    Car.staticRuning1(Thread.currentThread()); //同步类方法1
                }
            };
            t1.start();
    
            //线程2 类
            Thread t2 = new Thread(){
                @Override
                public void run() {
                    Car.staticRuning2(Thread.currentThread()); //同步类方法2
                }
            };
            t2.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Car类不能同时访问两个静态方法

    在这里插入图片描述

    synchronized代码块 — synchronized blocks

    • 另一种使用 intrinsic lock的方法是使用synchronized代码块
    public void transfer(int from, int to, int amount)
     {
    	synchronized (lock) // an ad-hoc lock
    	{
    	 accounts[from] -= amount;
    	 accounts[to] += amount;
    	}
    	 System.out.println(. . .);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    synchronized 保证原子性, 可见性, 有序性

    • 原子性: synchronized 关键字。锁操作,基于 monitorenter 和 monitorexit 字节码指令,保证同步块只有单一线程执行。
    • 可见性: synchronized 等锁机制。同步块的可见性是由“对一个变量执行 unlock 操作之前,必须先把此变量同步回主内存中(执行 store、write 操作)”这条规则获得的。
    • 有序性: synchronized 等锁机制,同步块的有序性是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的。
  • 相关阅读:
    MasaFramework -- 缓存入门与设计
    手撕Vuex-模块化共享数据下
    管理类联考——数学——汇总篇——知识点突破——算数——记忆
    Spring容器启动流程是怎样的?
    layui引入百度地图
    注册域名,购买阿里云服务器,备案,域名解析图文教程简介
    图论-最短路径问题
    司空见惯 - 英雄扫雷鼠
    批量删除wordpress文章修订版本/自动草稿残留数据(3种方法)及四种方法禁用WordPress文章历史修订/自动保存/自动草稿功能
    如何知道你的Linux内核占用的内存大小?
  • 原文地址:https://blog.csdn.net/weixin_38803409/article/details/126205158