synchronized


synchronized 是一种保护线程安全的机制。

synchronized语法

  1. 修饰任意的方法——方法修饰关键字
  • 普通方法
	synchronized void m2() {}
  • 静态方法
	static synchronized void m3() {}
  1. 同步代码块——可能出现在语句的位置(方法中,构造代码块中,静态代码块)
	Object  o = new Object();
	synchronized(o/*任意类型的引用*/){
	//语句
	}

预备知识

Class 是描述 类(Class)的类。
描述一个类的类,有且仅有一个。

例如:
Person p = new Person();
Class c1 = p.getClass();
Class c2 = Person.class;
c1 == c2 是true,引用指的是同一个对象;

Java中的对象中,有哪些数据:
在这里插入图片描述
任意的Java中的对象,都内含一把锁,这把锁被称为 同步锁/监视器锁
另外还包括Class对象

synchronized关键字的作用

以同步代码块为例:
在这里插入图片描述
这个引用不可以是null,否则会有NPE

注意:
synchronized修饰普通方法,视为对this加锁
synchronized修饰静态方法,视为对XX.class加锁

两个线程互斥

线程之间如何因为 锁 发生争抢——两个线程互斥
例如:

import java.util.Scanner;
import java.util.concurrent.TimeUnit;

class MyThread extends Thread {
    @Override
    public void run() {
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程:语句1");
        synchronized (SyncDemo2.o) {
            System.out.println("子线程: 语句2");
        }
        System.out.println("子线程: 语句3");
    }
}
public class SyncDemo2 {
    public static Object o;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        MyThread t = new MyThread();
        t.start();
        synchronized (o) {
            System.out.println("主线程:等待输入");
            scanner.nextLine();
            System.out.println("主线程: 马上释放锁");
        }
    }
}

只有前一个释放锁后,另外一个线程才能加锁开始执行(互斥)

例子:

void m1() {}
    synchronized void m2() {}
    static synchronized void m3() {}
    void m4() {
        synchronized (this) {}
    }
    static void m5() {
        synchronized (SyncDemo4.class) {}
    }
    void m6() {
        synchronized (SyncDemo4.class) {}
    }
    void m7() {
        synchronized (getClass()) {}
    }

在这里插入图片描述
上面的例子也体现了:
synchronized修饰普通方法,视为对this加锁
synchronized修饰静态方法,视为对XX.class加锁

两个线程要出现互斥:

1、两个线程都有加锁操作
2、两个线程加的是同一把锁

synchronized 加锁的过程

  1. 根据引用找到对象,加锁
  2. 加锁成功,直接向下执行
  3. 加锁失败
    1、把自己的对象放到这把锁的阻塞队列中
    2、把状态变更为一种阻塞状态(BLOCKED)——专为同步锁加锁失败设计
    3、主动放弃CPU

synchronized 释放锁的过程

1、释放锁
2、把这把锁的阻塞队列中等待的线程们,状态改为就绪(一个或多个,释放那个)

synchronized容易被忽视的地方

当加锁后,上下两个语句间的间隔不确定(不知道何时释放锁)

synchronized的作用

  1. 保护原子性 (需要保证互斥)
  2. 内存可见性一直
    1、一旦加锁成功,必须从主存储中,将最新的数据同步到工作存储中——保证线程看到的最新数据
    2、释放锁的时候,必须做一次把工作存储的数据刷会主存储的操作(保证主存储中是最新的数据)
  3. 代码重排序
    1、会一定程度上保持代码重排序
    在这里插入图片描述
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无赖H4

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值