关于synchronized中对象锁的介绍
根据获取的锁分类
1、获取对象锁
synchronized(this|object) {}
修饰非静态方法
在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java 对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。
2、获取类锁
synchronized(类.class) {}
修饰静态方法
在 Java 中,针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。
在 Java 中,每个对象都会有一个 monitor 对象,监视器。
1)某一线程占有这个对象的时候,先monitor 的计数器是不是0,如果是0还没有线程占有,这个时候线程占有这个对象,并且对这个对象的monitor+1;如果不为0,表示这个线程已经被其他线程占有,这个线程等待(锁的可见性)。当线程释放占有权的时候,monitor-1;
2)同一线程可以对同一对象进行多次加锁,+1,+1,重入性
例子:
创建三个线程,分别输出50次不同的数据
new Thread() { String str1="222"; @Override public void run() { super.run(); synchronized (str1) { for (int i=0; i<50;i++) { System.out.println("1"); } } } }.start();
new Thread() { String str1="222"; @Override public void run() { super.run(); synchronized (str1) { for (int i=0; i<50;i++) { System.out.println("2"); } } } }.start();
new Thread() { String str1="222"; @Override public void run() { super.run(); synchronized (str1) { for (int i=0; i<50;i++) { System.out.println("3"); } } } }.start();
假如传入锁为字符串且都分别为“111”,“222”,“333”则交替输出1,2,3 也就是说锁不同,就不存在唯一性,可以同时被三个线程运行;
假如传入锁为字符串且都是“222”,则控制台先输出50个1,再输出50个2,再输出50个3,锁具有唯一性,即锁只能被一个线程占有,即锁具有互斥性(除了当前运行的线程,其他线程不可以执行当前锁的其他代码);