一、 静态方法 vs 实例方法

核心区别:归属权不同

特性 静态方法 (static) 实例方法 (无 static)
归属 属于 类 (Class) 属于 对象 (Object)
调用 类名.方法() 对象名.方法()
内存 随类加载存在,常驻方法区 随对象创建存在,位于堆内存
访问权限 只能访问静态成员 (不能用 this) 可访问实例成员 + 静态成员
典型用途 工具类 (Math.max)、工厂方法 操作对象具体数据 (user.getName)

比喻:静态方法是“图纸上的说明书”(不依赖房子),实例方法是“房子里的功能”(必须先盖好房子)。


二、 锁的本质:我们在锁什么?

synchronized 关键字虽然写在方法上,但它锁住的永远是 对象

1. 锁对象的对应关系
  • 实例方法锁 (synchronized void method())

    • 🔒 锁住的是:this (当前具体的实例对象)。

    • 效果:只限制对同一个对象的并发访问。

  • 静态方法锁 (static synchronized void method())

    • 🔒 锁住的是:类名.class (全局唯一的 Class 对象)。

    • 效果:限制对该类所有对象的并发访问(全局锁)。

  • 代码块锁 (synchronized(obj) { ... })

    • 🔒 锁住的是:() 里的那个对象

    • 灵活性:这是最灵活的方式,可以锁 this,锁 Class,也可以锁自定义的 private lock


三、 锁的互斥(干扰)判断原则

判断两块代码是否互斥,只看一点:它们抢的是不是同一个对象?

场景 结果 原因
静态锁 vs 实例锁 互不干扰 一个锁 Class,一个锁 this,对象不同。
代码块 sync(this) vs 实例锁 互相干扰 都在抢当前对象 this
代码块 sync(Class) vs 静态锁 互相干扰 都在抢全局的 Class 对象。
代码块 sync(lockObj) vs 任何方法锁 互不干扰 lockObj 是独立的,与 thisClass 无关。

四、 关键概念辨析

1. this 指的是什么?
  • 定义this 是一个动态指针,代表**“当前调用这个方法的对象”**。

  • 口诀:谁调用,this 就指向谁。

  • 静态方法无 this:因为静态方法属于类,调用时可能还没有对象实例,所以不存在“我”的概念。

2. 锁的“君子协定” (最重要误区) ⚠️
  • 误区:以为 synchronized(lock) { count++ } 会物理锁住 count 变量,让别人无法访问。

  • 真相

    • 锁住的只是 lock 这个对象(像一个令牌/红绿灯)。

    • 防君子不防小人:如果另一个线程不检查 lock(不加 synchronized),直接去访问 count,它是完全可以访问并修改的!

  • 结论:锁并不是给数据加了保险箱,而是强制要求所有想要访问数据的线程遵守同一套排队规则


五、 黄金法则 (Best Practices)

为了保证线程安全,必须遵循以下规则:

  1. 统一锁对象:对于同一个共享资源(如变量 count),所有访问它的入口(读操作和写操作),必须使用同一个锁对象进行同步。

  2. 避免混用:不要一会儿用 synchronized(this),一会儿用 static synchronized 来保护同一个变量,因为它们是两把不同的锁。

  3. 推荐做法:使用 private final Object lock = new Object(); 作为专用锁对象,避免外部代码通过锁住 this 来干扰内部逻辑。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐