synchronized是Java中保证线程安全的基础机制,通过锁定对象控制多线程对共享资源的访问。它可修饰实例方法、静态方法或代码块,分别锁定当前实例、Class对象或指定对象,实现不同粒度的同步。修饰实例方法时,锁住this,同一实例的synchronized方法互斥;修饰静态方法时,锁住类的Class对象,所有实例共享该锁;使用synchronized(object)代码块可自定义锁对象,提升并发性能。相比ReentrantLock,synchronized语法简洁、自动释放锁、不易出错,且JVM已对其优化,适合大多数场景;而ReentrantLock提供公平锁、可中断、尝试获取锁等高级功能,适用于复杂并发需求。但synchronized存在性能开销,主要源于线程阻塞、上下文切换及锁升级,可通过缩小同步范围、使用并发工具类(如ConcurrentHashMap、Atomic类)或无锁编程来优化。总之,应根据实际需求权衡使用synchronized与ReentrantLock,在保证线程安全的同时兼顾性能。

Java中的
synchronized
synchronized
1. 修饰实例方法
当
synchronized
synchronized
synchronized
立即学习“Java免费学习笔记(深入)”;
public class Counter {
private int count = 0;
// 锁定当前Counter实例
public synchronized void increment() {
count++;
System.out.println(Thread.currentThread().getName() + " incremented to " + count);
}
public synchronized int getCount() {
return count;
}
// 这是一个非同步方法,可以被其他线程同时访问
public void doSomethingElse() {
System.out.println(Thread.currentThread().getName() + " is doing something else.");
}
}在这个例子中,
increment
getCount
synchronized
c.increment()
c
Counter
c.increment()
c.getCount()
c.doSomethingElse()
2. 修饰静态方法
当
synchronized
synchronized
public class StaticCounter {
private static int staticCount = 0;
// 锁定StaticCounter.class对象
public static synchronized void staticIncrement() {
staticCount++;
System.out.println(Thread.currentThread().getName() + " static incremented to " + staticCount);
}
public static synchronized int getStaticCount() {
return staticCount;
}
}这里,
staticIncrement
getStaticCount
StaticCounter.class
3. 修饰代码块
synchronized
public class BlockCounter {
private int count = 0;
private final Object lock = new Object(); // 专门用于同步的锁对象
public void increment() {
synchronized (lock) { // 锁定lock对象
count++;
System.out.println(Thread.currentThread().getName() + " block incremented to " + count);
}
}
public int getCount() {
synchronized (lock) {
return count;
}
}
// 也可以锁定this对象,效果与修饰实例方法类似
public void incrementWithThis() {
synchronized (this) { // 锁定当前BlockCounter实例
count++;
System.out.println(Thread.currentThread().getName() + " block with this incremented to " + count);
}
}
// 锁定Class对象,效果与修饰静态方法类似
public void incrementWithClass() {
synchronized (BlockCounter.class) { // 锁定BlockCounter.class对象
count++;
System.out.println(Thread.currentThread().getName() + " block with class incremented to " + count);
}
}
}使用代码块的好处是,我们可以将同步的范围限制在真正需要同步的代码上,而不是整个方法,这通常能提高并发性。选择哪个对象作为锁也很关键:
this
ClassName.class
synchronized
使用
synchronized
首先,最直接的开销就是线程阻塞和上下文切换。当一个线程试图获取已经被其他线程持有的
synchronized
其次,锁的膨胀和升级也是性能开销的一部分。JVM为了优化
synchronized
那么,如何规避这些性能问题呢?
缩小同步代码块的范围(Fine-Grained Locking):这是最常用也最有效的策略。只对真正需要保护的共享资源进行同步,而不是整个方法。例如,如果一个方法中只有几行代码涉及到共享变量,就只同步这几行,而不是整个方法。这能最大程度地减少锁持有的时间,从而降低线程阻塞的概率。
// 不推荐:整个方法都同步,即使大部分代码不涉及共享资源
public synchronized void processData() {
// 大量不涉及共享资源的代码...
sharedResource.update(); // 只有这一行需要同步
// 大量不涉及共享资源的代码...
}
// 推荐:只同步必要的部分
public void processDataOptimized() {
// 大量不涉及共享资源的代码...
synchronized (sharedResourceLock) {
sharedResource.update();
}
// 大量不涉及共享资源的代码...
}使用java.util.concurrent
synchronized
ReentrantLock
ReadWriteLock
Semaphore
ConcurrentHashMap
ReentrantLock
synchronized
ReadWriteLock
ConcurrentHashMap
避免不必要的同步:有时候,我们可能会过度同步。在确保线程安全的前提下,检查是否所有
synchronized
无锁编程(Lock-Free Programming):对于一些特定的场景,可以考虑使用
Atomic
AtomicInteger
AtomicLong
总的来说,
synchronized
synchronized
理解
synchronized
1. 修饰实例方法 (public synchronized void methodA()
synchronized(this)
this
synchronized
synchronized(this)
synchronized
synchronized(this)
synchronized
synchronized
Account
Account
2. 修饰静态方法 (public static synchronized void staticMethodA()
synchronized(ClassName.class)
synchronized
synchronized(ClassName.class)
synchronized
synchronized(ClassName.class)
synchronized
getInstance()
3. synchronized(object)
锁定对象: 指定的任意对象
object
行为: 线程获取的是
object
object
并发性: 这种方式提供了最大的灵活性。你可以根据需要创建多个锁对象,每个锁对象只保护它所关联的那部分共享资源。这样,不相关的共享资源可以独立地被并发访问,从而提高整体并发度。
适用场景:
细粒度锁定: 当一个类中有多个独立的共享资源,且它们之间没有关联时,可以为每个资源创建独立的锁对象,实现更细粒度的控制,避免不必要的阻塞。
public class DataProcessor {
private List<String> listA = new ArrayList<>();
private List<String> listB = new ArrayList<>();
private final Object lockA = new Object();
private final Object lockB = new Object();
public void addToListA(String item) {
synchronized (lockA) { // 只锁定listA
listA.add(item);
}
}
public void addToListB(String item) {
synchronized (lockB) { // 只锁定listB
listB.add(item);
}
}
}在这个例子中,
addToListA
addToListB
当需要同步的代码块不属于当前对象,或者需要跨越多个对象进行同步时。
避免将锁暴露给外部,使用
private final
选择哪种锁定方式,关键在于你想要保护什么,以及希望达到怎样的并发程度。锁定实例方法或
this
synchronized(object)
synchronized
java.util.concurrent.locks.ReentrantLock
在Java并发编程中,
synchronized
ReentrantLock
synchronized
synchronized
lock()
unlock()
synchronized
synchronized
synchronized
ReentrantLock
ReentrantLock
灵活性与功能扩展:
ReentrantLock
java.util.concurrent.locks
synchronized
new ReentrantLock(true)
tryLock()
lockInterruptibly()
newCondition()
ReentrantLock
Condition
await()
signal()
signalAll()
object
wait()
notify()
notifyAll()
isLocked()
isHeldByCurrentThread()
getQueueLength()
手动管理: 需要显式地调用
lock()
unlock()
finally
unlock()
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock(); // 必须在finally块中释放锁
}权衡考量与选择:
synchronized
synchronized
ReentrantLock
ReentrantLock
我的看法:
我个人觉得,对于大多数日常开发任务,
synchronized
ReentrantLock
synchronized
ReentrantLock
ReentrantLock
以上就是Java中synchronized关键字的使用方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号