对象锁:锁的是这个对象。
全局锁:锁的是那个写了synchronized关键字的方法或者代码块。
这里主要去聊全局锁
当java关键字 Synchronized()代码块锁随便的一个类比如,Integer.class时(或者一个静态变量(前提是不改变指向))
比如下列代码
package cn.com.demo.utils;
import lombok.Getter;
import java.util.stream.IntStream;
/**
* @author JMWANG
*/
public class Tes2Thread {
@Getter
private static int counter = 0;
public static int reset() {
counter = 0;
return counter;
}
private static Integer locker = new Integer(0);
public void right() {
synchronized (locker) {
counter++;
}
}
public static void main(String[] args) {
Tes2Thread.reset();
//多线程循环一定次数调用Data类不同实例的wrong方法
IntStream.rangeClosed(1, 1000000).parallel().forEach(i -> new Tes2Thread().right());
System.out.println(Tes2Thread.getCounter());
}
}
最后得到的解决无疑是1000000,但是明明被保护的对象是 公共静态变量counter ,为什么要锁一个毫无关系的一个类(或者一个静态不变的对象实例)。最后达到的效果确实保护了 这个counter 变量。
从字节码来分析
public void right();
Code:
0: getstatic #3 // Field locker:Ljava/lang/Integer;
3: dup
4: astore_1
5: monitorenter //通过Synchronized获取了一个监视器,将静态的所有数据都保护了起来,并且进行了操作。
6: getstatic #2 // Field counter:I
9: iconst_1
10: iadd
11: putstatic #2 // Field counter:I
14: aload_1
15: monitorexit //退出监视器
16: goto 24
19: astore_2
20: aload_1
21: monitorexit
22: aload_2
23: athrow
24: return
Exception table:
from to target type
6 16 19 any
19 22 19 any
当监视器启动这是我们使用的是全局锁。当全局锁进入了monitor就不会让其他线程进入,只能等待。从而达到同步的效果。