概述
synchronized 是 Java 内建的同步机制,它提供了互斥的语义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能阻塞在那里。
在 Java 5 以前,synchronized是仅有的线程同步手段。在代码中, synchronized 可以用来修饰方法,也可以使用在特定的代码块上,本质上 synchronized 方法等同于把方法全部语句用 synchronized 块包起来。
synchronized同步锁在加锁和解锁的过程中,依赖于操作系统互斥锁(Mutex Lock)所实现的锁,消耗资源,属于重量级锁(在Java1.6以后进行了优化)。另外在获取锁时,必须一直等待,没有额外的尝试机制。
synchronized底层实现
使用synchronized保证线程安全,就是保证原子性,简单说就是执行过程中不会被其他线程干扰。
通过下面的代码案例,观察一下synchronized的用法以及底层实现。
案例1:通过两个线程对变量sharedState进行10w次操作,观察每次操作后former与latter之间的关系。
public class ThreadSafeSample {
public int sharedState;
public void nonSafeAction() {
while (sharedState < 100000) {
int former = sharedState++;
int latter = sharedState;
if (former != latter - 1) {
System.out.printf("数据观察结果: former is %d,latter is %d", former,latter);
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadSafeSample sample = new ThreadSafeSample();
Thread threadA = new Thread(){
public void run(){
sample.nonSafeAction();
}
};
Thread threadB = new Thread(){
public void run(){
sample.nonSafeAction();
}
};
threadA.start();
threadB.start();
threadA.join();
threadB.join();
System.out.println(sample.sharedState);
}
}
我们发现运行结果,并不是我们期望中的former等于latter,它们之间存在这误差。这部分误差是由于线程不安全导致的。
运行结果:
数据观察结果: former is 22502,latter is