Java synchronized 学习笔记
1. synchronized 关键字的作用
在Java中,synchronized关键字是用来控制线程同步的,在多线程的环境下,控制 synchronized 修饰的代码段不被多个线程同时执行。synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性(a) synchronized 关键字可以实现操作的原子性:
Java 中每一个对象都可以作为锁,这是 synchronized 实现同步的基础。所有对象都自动含有单一的锁,JVM 负载跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为零。在任务(线程)第一次给对象加锁的时候计数变为 1,每当这个相同的线程在对象上获得锁时,计数会递增。只有首先获得锁的线程才能继续获取该对象上的多个锁。每当这个获得锁线程离开一个 synchronized 方法时,计数递减,当计数为零时,锁被完全释放,别的线程就可以使用此资源了。synchronized 关键字所包括的临界区的排他性保证了任何一个时刻只有一个线程能够执行临界区中的代码,这使得临界区的代码代表了一个原子操作。
(b) synchronized 保证了内存可见性:
synchronized 关键字保证了一个线程执行临界区的代码时对共享变量所做的修改对于其他访问该变量的线程而言总是可见的,即对该变量的修改会被写入内存,而不仅仅是当前线程所在的 CPU 的缓存区,这使得其他 CPU 缓存区中所存储的该变量的值失效,从而得以更新为内存中该变量修改后的最新值。2. synchronized 用法
synchronized 关键字可以用来修饰方法或代码块:public class Foo {
private byte[] lock = new byte[0];
public synchronized static void staticMethod() {
System.out.println("Need to get lock of current class");
}
public synchronized void instanceMethod() {
System.out.println("Need to get lock of current instance");
}
public void codeBlock() {
System.out.println("Foo");
synchronized(lock) {
System.out.println("Need to get lock of the byte array object");
}
}
}
Note:
(1) synchronized 修饰类方法时,获取的是类的锁,当某个线程调用了该类方法时,其他所有试图访问该方法的线程都必须等待,直到获得了该类的锁
(2) synchronized 修饰实例方法时,获取的是该实例对象的锁,其他所有试图访问该实例的任何一个 synchronized 的方法(不仅仅是当前正在被调用的这个 synchronized 方法)的线程都必须等待,直到获得了该对象的锁
(3) synchronized 修饰代码块时,任何访问该代码块的线程必须先获得 synchronized 所作用的那个对象的锁, 所以上面修饰类方法和实例方法的 synchronized 也可以这样写,它们分别以相应的类和实例作为同步对象来获取它们的锁:
public class Foo {
private byte[] lock = new byte[0];
public static void staticMethod() {
synchronized(Foo.class) {
System.out.println("Need to get lock of current class");
}
}
public void instanceMethod() {
synchronized(this) {
System.out.println("Need to get lock of current instance");
}
}
public void codeBlock() {
System.out.println("Foo");
synchronized(lock) {
System.out.println("Need to get lock of the byte array object");
}
}
}
参考文献:
http://www.importnew.com/23511.html
https://www.cnblogs.com/beiyetengqing/p/6213437.html
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html