网站流量一直下降/去了外包简历就毁了吗
synchronized锁的什么资源
- 前言
- 声明一个加synchronized的类
- 执行代码测试
- 结论
前言
我们都用过synchronized这个关键字,常见的使用方式是这样synchronized(资源){代码},这是显示的声明锁资源,很明显知道要竞争锁资源是什么。
我们也知道在两个不同方法上架synchrinized关键字,这两个方法在不同线程中会互相等待,他们好像获取的是同一个资源,那这个锁资源是什么呢?是方法的引用obj::method?下面我们来验证一下
声明一个加synchronized的类
public class TestSynchronize {static Object get1 = new Object();public synchronized void get() {// synchronized (this) {System.out.println(Thread.currentThread().getName()+"get得到锁"+this);try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}
// }}public synchronized void ge2t() {System.out.println(Thread.currentThread().getName()+"ge2t得到锁"+this);try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static synchronized void staticget() {System.out.println(Thread.currentThread().getName()+"staticget得到锁");try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static synchronized void staticge2t() {System.out.println(Thread.currentThread().getName()+"staticge2t得到锁");try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
执行代码测试
- 我们先看下非静态方法的情况
public static void main(String[] args) {TestSynchronize stu = new TestSynchronize();new Thread(()->{synchronized (stu) {System.out.println(Thread.currentThread().getName()+"获取锁"+stu+"\t"+System.currentTimeMillis());try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"释放锁"+"\t"+System.currentTimeMillis());}},"a").start();;new Thread(()->{System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());stu.get();System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());},"b").start();new Thread(()->{System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());stu.ge2t();System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());},"c").start();}
a获取锁Test.Test.TestSynchronize@1d1ae28f 1635507748132
b尝试 1635507748133
c尝试 1635507748133
a释放锁 1635507753143
c\t ge2t得到锁Test.Test.TestSynchronize@1d1ae28f 1635507753143
c结束 1635507756155
b get得到锁Test.Test.TestSynchronize@1d1ae28f 1635507756155
b结束 1635507759166
我们看待a线程获取锁之后,b,c线程都在等待锁,c获取锁后b线程在等待锁
- 在看下静态方法上的synchronized
public static void main(String[] args) {new Thread(()->{synchronized (TestSynchronize.class) {System.out.println(Thread.currentThread().getName()+"获取锁"+TestSynchronize.class +"\t"+System.currentTimeMillis());try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"释放锁"+"\t"+System.currentTimeMillis());}},"astatic").start();new Thread(()->{System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());TestSynchronize.staticget();System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());},"estatic").start();new Thread(()->{System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());TestSynchronize.staticge2t();System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());},"fstatic").start();}
astatic 获取锁class Test.Test.TestSynchronize 1635507551822
estatic 尝试 1635507551822
fstatic 尝试 1635507551823
astatic 释放锁 1635507556825
fstatic\t staticge2t得到锁 1635507556825
fstatic 结束 1635507559834
estatic\t staticget得到锁 1635507559834
estatic 结束 1635507562843
我们可以看到astatic线程获取锁后,estatic fstatic两个线程中的静态方法都在等待锁,fstatic得到锁之后estatic 在等待fstatic释放锁。
结论
- 当在静态方法上加synchronized时,实际上锁的资源是class这个类等效代码是synchronized (TestSynchronize.class) ,所以两个静态方法都加synchronized关键字时竞争的是同一个锁资源。
- 当在普通方法上加锁时,实际上锁的是实体对象,也就是this,上面打印出来是TestSynchronize@1d1ae28f这个对象,所以两个普通方法竞争的也是同一个锁资源,也会互相等待。