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 自旋,避免阻塞 低并发,短时间竞争

  • 重量级锁

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

源码

源码

相关推荐
苏三说技术1 小时前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎2 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode2 小时前
Redis 在生产项目的使用
前端·后端
用户559822481222 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode2 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战2 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha2 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端
Csvn2 小时前
Docker 容器管理入门 — 从镜像到容器编排
后端
用户762352425913 小时前
ShardingJDBC
后端
行者全栈架构师3 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端