java中的synchronize(修饰方法)

本文详细解析了Synchronized修饰符的应用,包括对普通方法和静态方法的修饰,并通过实例展示了其如何实现线程同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        Synchronize对方法的修饰可分为对一般方法的修饰和对静态方法的修饰,首先看Synchronize对一般方法的修饰。

        Synchronize对一般方法的修饰和对代码块的修饰没有什么区别,对代码块的修饰作用范围是Synchronize(this){ // 作用范围},大括号中的代码是作用范围,而对方法修饰的作用范围就是整个方法。如果把代码块中的代码提出来作为一个方法二者没有什么本质上的区别。

        将上篇博客中的例子修改为如下:(不同之处为将Synchronize原先只对for循环修改为对整个run方法的修饰)

<span style="font-size:18px;">public synchronized void run() {
   for (int i = 0; i < 5; i++) {
      try {
        System.out.println(Thread.currentThread().getName() + ":" +(count++));
         Thread.sleep(1000);
      } catch(InterruptedException e) {
         e.printStackTrace();
      }
   }
}</span>

         运行结果和对只修饰代码块的结果是一样的。

 

        除了对一般方法修饰Synchronize还可以对静态方法进行修饰,我们知道类中的静态方法是属于所有实例化的对象的,可以推断如果Synchronize修饰一个静态方法那么该类所有实例化出来的对象对这个方法都是线程同步的。通过如下的实例验证:

<span style="font-size:18px;">public class SyncThread implementsRunnable{
     private static int count;
     public SyncThread() {
         count = 0;
     }
     public synchronized static void test() {     
          for (int i = 0; i < 5; i++) {
              try {
                    System.out.println(Thread.currentThread().getName() + ":" +(count++));
                    Thread.sleep(1000);
               } catch (InterruptedException e) {
                     e.printStackTrace();
              }
          }                       
      }
      public void run() {
            test();
      }
      public int getCount() {
                 return count;
       }
 
         publicstatic void main(String[] args){
                   SyncThreadsyncThread1 = new SyncThread();
                   SyncThreadsyncThread2 = new SyncThread();
                   Threadthread1 = new Thread(syncThread1, "SyncThread1");
                   Threadthread2 = new Thread(syncThread2, "SyncThread2");
                   thread1.start();
                   thread2.start();
         }
}</span>

结果展示:


结果分析:

       本次虽然也是实例化的两个线程类,但是运行的结果却和只有一个线程实例类是一样的,因为在run中调用的是test这个静态的方法,这个方法时属于所有的对象,所以即使实例化的三个线程类,它们还是保持同步的。


小结:

      1、  定义接口方法是不能够使用Synchronize

      2、  类的构造方法不可以使用

      3、  Synchronize不能继承

<think>好的,用户现在问的是“synchronize修饰静态方法时锁住的是”。我需要详细解释当在静态方法上使用synchronized关键字时,锁住的对象是什么。 首先,我需要回顾一下Javasynchronized的用法。对于实例方法synchronized锁住的是当前实例对象,即this。而静态方法属于类级别,不属于任何实例,所以锁的对象应该不同。 接下来,我需要确认静态方法使用的锁到底是什么。根据Java规范,静态同步方法使用的锁是该类的Class对象。例如,如果类名为MyClass,那么锁就是MyClass.class。这样,所有调用该静态方法的线程都必须获取这个Class对象的锁才能执行。 然后,要考虑用户可能的疑问,比如为什么是Class对象而不是其他。需要解释类加载机制,每个类在JVM中只有一个Class对象,因此静态方法的锁是全局唯一的,确保同一时间只有一个线程能执行该类的静态同步方法。 可能还需要对比实例方法和静态方法的锁区别,帮助用户理解不同情况下的锁行为。例如,实例方法锁的是实例对象,不同实例之间互不影响;而静态方法锁的是类对象,所有实例的静态方法调用都会互斥。 此外,用户可能想知道这种锁对性能的影响,或者在实际开发中如何正确使用。可以简要提到在高并发环境下,过度使用静态同步方法可能导致性能问题,因为所有相关线程都需要竞争同一个锁,建议根据具体情况选择合适的同步策略。 还要注意用户是否可能有更深层的需求,比如他们是否在调试多线程问题,或者在设计类结构时需要同步机制。需要确保解释清晰,提供足够的例子,比如代码片段,说明静态同步方法的使用和锁的行为。 最后,检查是否有常见的误解需要澄清,例如是否锁住了整个类,或者是否影响其他静态方法。需要明确说明,只有同样使用synchronized修饰的静态方法才会共享同一个锁,非静态方法或其他未同步的方法不受影响。</think>当使用`synchronized`修饰静态方法时,**锁住的是当前类的`Class`对象**。这是Java多线程同步的关键机制之一,具体原理和影响如下: --- ### 一、核心原理 #### 1. **锁的载体** ```java public class MyClass { public static synchronized void staticMethod() { // 锁的是MyClass.class } } ``` - 静态方法属于类级别,而非实例级别。 - 锁对象为该类的**Class对象**(即`MyClass.class`),在JVM中每个类仅有一个Class对象。 #### 2. **与实例方法的对比** | 方法类型 | 锁对象 | 作用范围 | |----------------|---------------------|----------------------------| | 实例方法 | 当前实例 (`this`) | 仅影响同一实例的同步方法调用 | | 静态方法 | 类的`Class`对象 | 影响所有实例的静态方法调用 | --- ### 二、具体场景分析 #### 1. **多线程竞争Class锁** ```java // 线程1调用静态同步方法 new Thread(() -> MyClass.staticMethod()).start(); // 线程2调用另一个实例的静态同步方法 new Thread(() -> MyClass.staticMethod()).start(); ``` - 即使创建多个`MyClass`实例,所有静态同步方法共享同一个锁(`MyClass.class`)。 - 线程1和线程2会因竞争同一把锁而互斥。 #### 2. **与非静态方法的互斥性** ```java public class MyClass { public static synchronized void staticMethod() {} // 锁Class对象 public synchronized void instanceMethod() {} // 锁this实例 } ``` - 静态方法(锁`Class对象`)与实例方法(锁`this`)**不会互斥**,因为锁对象不同。 --- ### 三、底层实现验证 #### 1. 字节码分析 编译后,静态同步方法的字节码包含以下指令: ```java public static synchronized void staticMethod(); descriptor: ()V flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED ``` - `ACC_SYNCHRONIZED`标志表示该方法需要获取锁。 - JVM自动选择`Class对象`作为锁。 #### 2. 等效代码展开 静态同步方法等价于: ```java public static void staticMethod() { synchronized (MyClass.class) { // 显式锁Class对象 // 方法体 } } ``` --- ### 四、应用建议 | 场景 | 最佳实践 | |-----------------------|--------------------------------------------------------------------------| | **全局资源配置** | 静态同步方法适合保护全局资源(如数据库连接池) | | **高并发性能敏感场景** | 避免过度使用静态同步,改用`ReentrantLock`或细粒度锁 | | **防止死锁** | 静态锁和实例锁混合使用时,需严格定义锁的获取顺序 | --- ### 五、常见误区 1. **误区**:静态同步方法会锁住所有实例 **纠正**:静态方法仅影响其他静态同步方法,不影响实例方法。 2. **误区**:子类继承父类的静态同步方法锁 **纠正**:子类静态方法锁的是子类的`Class对象`,与父类无关。 --- 通过理解这一机制,可以更精准地设计线程安全方案,避免因锁范围过大导致的性能问题。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值