1. Synchronized
关键字的作用
synchronized
是 Java 中的关键字,用于实现线程的同步,确保多个线程之间对共享资源的安全访问。它可以被用于方法、代码块以及静态方法上。
-
在方法上使用: 锁定整个方法,确保同一时间只有一个线程可以执行该方法。
public synchronized void synchronizedMethod() { // 同步的方法体 }
-
在代码块上使用: 锁定指定的对象,只有获得该对象的锁的线程才能执行该代码块。
public void someMethod() { // 非同步代码 synchronized (lockObject) { // 同步代码块 } // 非同步代码 }
2. Synchronized
原理
synchronized
关键字的原理涉及到对象头中的锁标志位(Lock Flag)和互斥量(Mutex)。
-
获取锁: 当线程尝试进入一个使用
synchronized
修饰的方法或代码块时,它会尝试获取对象的锁。 -
锁标志位: 对象头中有一个锁标志位,初始值为无锁状态。当线程成功获取锁时,锁标志位变为锁定状态。
-
互斥量: 如果锁已经被其他线程持有,当前线程会进入阻塞状态。此时,JVM 会使用互斥量来协调线程的访问。
3. 锁优化
a. 轻量级锁
JDK 1.6引入了轻量级锁,旨在减少传统的重量级锁的性能开销。在没有竞争的情况下,JVM 会尝试使用轻量级锁来提高性能。轻量级锁采用CAS(Compare and Swap)操作来尝试获取锁,避免了传统锁的互斥操作。
public class LightweightLockExample {
private int sharedResource = 0;
public void synchronizedMethod() {
synchronized (this) {
// 同步代码块
sharedResource++;
}
}
}
b. 偏向锁
JDK 1.6还引入了偏向锁,该锁假设在大多数情况下,锁总是由同一线程多次获得。因此,当一个线程获得锁时,会标记对象头,并在以后尝试获取锁时,不再使用互斥,直接进入临界区。,避免了对锁的互斥操作,提高了单线程访问的性能。
public class BiasedLockExample {
private int sharedResource = 0;
public synchronized void synchronizedMethod() {
// 同步代码块
sharedResource++;
}
}
c. 无锁优化
针对一些高度竞争的情况,JDK 1.8 引入了无锁优化。通过一些乐观锁的机制,避免了对锁的争用。
import java.util.concurrent.atomic.AtomicInteger;
public class NoLockOptimizationExample {
private AtomicInteger sharedResource = new AtomicInteger(0);
public void nonBlockingMethod() {
// 非阻塞代码
sharedResource.incrementAndGet();
}
}
总结
synchronized
关键字在Java中起到了关键的同步作用,确保多线程访问共享资源的安全性。