synchronized method 和 synchronized static method 的区别

本文探讨了Java中synchronized关键字的使用,特别是在方法级别上的应用。解释了synchronized method和synchronized static method的区别,即它们如何锁定实例对象与类对象,并通过具体代码示例说明了这一点。

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

   书上解释的很简单也很清楚,只是用起来会有一点问题。

synchronized method 的同步对象是指类实例对象,

synchronized static method 的同步对象指类本身,也就是所有对象共享这个同步对象。

 

问题出在 

public int kk(){

   g();

}

当在kk中调用g()时,到底使用了哪个对象?是使用了实例对象!无论你是用g()调用,还是even.g()调用,实例对象优先。

要使用类对象的话,你必须在even类外调用 Even.g()

 

 

class Generator{

private  static int even =0;

 

Random r = new Random(1000);

 

Generator(){

 

}

 

public synchronized  int f(){

even ++;

 

 

 

even ++;

 

return even;

}

 

public  synchronized static int g() {

even ++;

try {

Thread.sleep(10);  

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

even ++;

 

return even;

}

public int kk(){

   g();

}

}

 

 

<think>我们正在讨论Java中volatilesynchronized关键字的区别。根据提供的引用,我们可以总结如下:1.**volatile关键字**:-只能用于变量(不能用于方法或代码块)。-保证变量的可见性:当一个线程修改了volatile变量的值,新值对其他线程是立即可见的。-不保证原子性:例如,自增操作(i++)不是原子操作,即使变量是volatile,多线程同时修改仍可能导致问题。-使用场景:通常用于状态标志(如引用[4]中的示例)或者一次性发布(如单例模式的双重检查锁定)。2.**synchronized关键字**:-可以修饰方法(实例方法静态方法)或代码块。-保证可见性原子性:进入同步代码块前,会清空工作内存,从主内存重新读取变量;退出同步代码块时,会将修改后的变量刷新回主内存。同时,同步代码块内的操作是原子执行的。-使用场景:需要保证多个线程访问共享资源时的同步,例如对共享变量的复合操作。**区别总结**:-**作用范围**:volatile仅能用于变量,而synchronized可以用于方法代码块。-**性能**:volatile是轻量级的同步机制,性能通常比synchronized好(引用[2])。-**可见性**:两者都能保证可见性,但synchronized还会保证原子性。-**原子性**:volatile不保证原子性,synchronized保证原子性。-**使用场景**:volatile适用于一个线程写、多个线程读的场景;synchronized适用于多个线程读写共享资源的场景。**示例说明**:-volatile示例(状态标志):```javaprivatevolatilebooleanrunning=true;```一个线程修改`running`为false,另一个线程会立即看到并停止循环。-synchronized示例(单例模式的双重检查锁定):```javaprivatestaticvolatileSingletoninstance;publicstaticSingletongetInstance(){if(instance==null){synchronized(Singleton.class){if(instance==null){instance=newSingleton();}}}returninstance;}```这里使用volatile确保`instance`的可见性,同时使用synchronized保证创建实例的原子性。§§相关问题§§1.为什么volatile不能保证原子性?请举例说明。2.在单例模式的双重检查锁定中,为什么需要同时使用volatilesynchronized?3.除了状态标志单例模式,volatile还有哪些典型应用场景?4.synchronized锁的粒度有哪些?如何选择?</think>### Java中`volatile``synchronized`关键字的区别 #### 1. **核心功能差异** - **`volatile`**: - 仅保证变量的**可见性**:当一个线程修改`volatile`变量时,新值立即对其他线程可见(强制刷新主内存)[^2][^4]。 - **不保证原子性**:例如`count++`(非原子操作)在多线程下仍可能出错。 - 适用场景:独立状态标志(如`boolean running`)或单次发布(如单例模式的双重检查锁定)[^4]。 - **`synchronized`**: - 保证**可见性原子性**:通过锁机制确保代码块/方法内操作不可分割,且操作结果对所有线程立即可见[^2][^4]。 - 适用场景:多线程共享资源的复合操作(如转账、计数器累加)。 #### 2. **作用范围** - **`volatile`**: - **仅修饰变量**(如`private volatile int count;`)[^2]。 - **`synchronized`**: - 修饰**代码块**(锁定指定对象): ```java synchronized (lockObject) { /* 临界区 */ } ``` - 修饰**实例方法**(锁定当前对象): ```java public synchronized void method() { ... } ``` - 修饰**静态方法**(锁定类对象): ```java public static synchronized void staticMethod() { ... } ```[^3] #### 3. **性能差异** - **`volatile`**: - 轻量级同步,无锁操作,性能开销小(仅读写内存屏障)[^2]。 - **`synchronized`**: - 重量级同步,涉及锁竞争、上下文切换,性能开销较大(JDK优化后如偏向锁/自旋锁可缓解)[^2]。 #### 4. **典型应用场景对比** | **场景** | **`volatile`适用性** | **`synchronized`适用性** | |------------------------|----------------------------|--------------------------------| | 状态标志(如`boolean running`) | ✅(一写多读) | ⚠️(过度开销) | | 单例模式(双重检查锁定) | ✅(配合`synchronized`) | ✅(直接锁定方法) | | 计数器累加(`count++`) | ❌(不保证原子性) | ✅(保证原子操作) | | 复合操作(如转账) | ❌ | ✅ | #### 5. **示例说明** - **`volatile`可见性示例**: ```java public class VolatileExample { private volatile boolean running = true; // 状态标志 public void stop() { running = false; } // 修改后立即可见 public void run() { while (running) { /* 执行任务 */ } // 其他线程立刻感知到变化 } } ```[^4] - **`synchronized`原子性示例**: ```java public class Counter { private int count = 0; public synchronized void increment() { count++; // 原子操作 } } ``` #### 6. **总结对比表** | **特性** | `volatile` | `synchronized` | |------------------|-----------------------------|------------------------------| | **可见性** | ✅ | ✅ | | **原子性** | ❌ | ✅ | | **作用对象** | 变量 | 代码块/方法 | | **性能开销** | 低 | 高 | | **适用场景** | 状态标志、单次发布 | 复合操作、共享资源竞争 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值