synchronized

几种方式

修饰方法

同一个实例,同一时间只能有一个线程访问该方法 作用域是同一个实例

java 复制代码
package com.jysemel.java.basic.thread.lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

public class SynchronizedDemo1 {

    @SneakyThrows
    public synchronized void say() {
        System.out.println("static1 -------------" + Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(10);
        System.out.println("static1-----------------end" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // 同一个实例
        SynchronizedDemo1 demo1 = new SynchronizedDemo1();
        new Thread(demo1::say).start();
        new Thread(demo1::say).start();

        // 不同实例
        SynchronizedDemo1 demo2 = new SynchronizedDemo1();
        SynchronizedDemo1 demo3 = new SynchronizedDemo1();
        new Thread(demo2::say).start();
        new Thread(demo3::say).start();

    }
}

修饰静态方法

作用域全局

java 复制代码
package com.jysemel.java.basic.thread.lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

public class SynchronizedDemo2 {

    @SneakyThrows
    public static synchronized void say() {
        System.out.println("static1 -------------" + Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(10);
        System.out.println("static1-----------------end" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        new Thread(SynchronizedDemo2::say).start();
        new Thread(SynchronizedDemo2::say).start();
    }
}

修饰代码块(同步代码块)

同一个实例,同一时间只能有一个线程访问该方法 如果是静态对象,则作用域全局

java 复制代码
package com.jysemel.java.basic.thread.lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

public class SynchronizedDemo3 {


    private final Object obj = new Object();
    private final static Object staticObj = new Object();

    @SneakyThrows
    public void say(String name) {
        synchronized (obj) {
            System.out.println(name + "say -------------" + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(10);
            System.out.println(name + "say-----------------end " + Thread.currentThread().getName());
        }
    }

    @SneakyThrows
    public void staticSay(String name) {
        synchronized (staticObj) {
            System.out.println(name + "staticSay -------------" + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(10);
            System.out.println(name + "staticSay-----------------end " + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
//        // 同一个实例
//        SynchronizedDemo3 demo1 = new SynchronizedDemo3();
//        new Thread( () -> demo1.say("thread1 ")).start();
//        new Thread( () -> demo1.say("thread2 ")).start();
//
//        //不同实例
//        SynchronizedDemo3 demo2 = new SynchronizedDemo3();
//        SynchronizedDemo3 demo3 = new SynchronizedDemo3();
//        new Thread( () -> demo2.say("thread3 ")).start();
//        new Thread( () -> demo3.say("thread4 ")).start();

        //不同实例,静态对象
        SynchronizedDemo3 demo4 = new SynchronizedDemo3();
        SynchronizedDemo3 demo5 = new SynchronizedDemo3();
        new Thread( () -> demo4.staticSay("thread4 ")).start();
        new Thread( () -> demo5.staticSay("thread5 ")).start();

        System.out.println("finished");

    }

}

修饰代码块(this和类)

同一个实例,同一时间只能有一个线程访问该方法 类,则作用域全局

java 复制代码
package com.jysemel.java.basic.thread.lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

public class SynchronizedDemo4 {

    @SneakyThrows
    public void say(String name) {
        synchronized (this) {
            System.out.println(name + "say -------------" + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(10);
            System.out.println(name + "say-----------------end " + Thread.currentThread().getName());
        }
    }

    @SneakyThrows
    public void staticSay(String name) {
        synchronized (SynchronizedDemo4.class) {
            System.out.println(name + "staticSay -------------" + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(10);
            System.out.println(name + "staticSay-----------------end " + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        // 同一个实例
        SynchronizedDemo3 demo1 = new SynchronizedDemo3();
        new Thread( () -> demo1.say("thread1 ")).start();
        new Thread( () -> demo1.say("thread2 ")).start();

        //不同实例
        SynchronizedDemo3 demo2 = new SynchronizedDemo3();
        SynchronizedDemo3 demo3 = new SynchronizedDemo3();
        new Thread( () -> demo2.say("thread3 ")).start();
        new Thread( () -> demo3.say("thread4 ")).start();

        //不同实例,静态对象
//        SynchronizedDemo4 demo4 = new SynchronizedDemo4();
//        SynchronizedDemo4 demo5 = new SynchronizedDemo4();
//        new Thread( () -> demo4.staticSay("thread4 ")).start();
//        new Thread( () -> demo5.staticSay("thread5 ")).start();

        System.out.println("finished");

    }

}

锁升级

synchronized 的锁升级过程总结

  • 偏向锁

记录线程 ID,无竞争快速获取 单线程访问

  • 轻量级锁

CAS 自旋,避免阻塞 低并发,短时间竞争

  • 重量级锁

阻塞线程,性能低 高并发激烈竞争

源码

源码

相关推荐
青云计划8 小时前
知光项目知文发布模块
java·后端·spring·mybatis
Victor3568 小时前
MongoDB(9)什么是MongoDB的副本集(Replica Set)?
后端
Victor3569 小时前
MongoDB(8)什么是聚合(Aggregation)?
后端
yeyeye11110 小时前
Spring Cloud Data Flow 简介
后端·spring·spring cloud
Tony Bai10 小时前
告别 Flaky Tests:Go 官方拟引入 testing/nettest,重塑内存网络测试标准
开发语言·网络·后端·golang·php
+VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue鲜花商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
程序猿阿伟11 小时前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
小小张说故事11 小时前
SQLAlchemy 技术入门指南
后端·python
识君啊11 小时前
SpringBoot 事务管理解析 - @Transactional 的正确用法与常见坑
java·数据库·spring boot·后端
想用offer打牌12 小时前
MCP (Model Context Protocol) 技术理解 - 第五篇
人工智能·后端·mcp