故事搞起来~
从今天开始,姑娘我将要回归“起跑线”,含着眼泪默默的将大学老师奋笔疾书教过的“理论”以及工作N年后并曾未总结过的“实战经验”一并拾起来,我要向专业再靠近一步,近一步......心里默默叨念:我不仅可以靠颜值吃饭,更可以在实力的路上越走越远......
这一切的一切动力源于两个原因:1·看到一个毕业不久(好像是哈,反正比我小)的小弟弟在各大网站及b站发表的系列文章,其广度其深度让已经毕业四年的我深感惭愧(姑娘我也是有实力的);2·最近入手一份“价值不菲”(没有多贵哈,利用好了决定价值不菲)的学习资料,出于心疼钱,我决定好好学习,天天向上😭😭
正文还是要有滴~
说起“synchronized",我们会想到什么呢?锁?重量级锁?volatile?reentrantLock ......一切的一切都源于我们的并发与多线程,但说实话,工作的这几年,依旧没有透彻的搞明白并发多线程,但这依旧不影响自己建立这样的知识节点树(之前可能会怕别人嘲笑自己的无知而害怕说错,现在我倒认为:说错没关系,脑子里有错误的理解也没关系,因为随着不断的学习,脑子里的那张网图会被不断更新与替换)
今天只是初遇,毕竟第一次见面,咱就不问人家几套房,几辆车了吧,咱就看看帅不帅,眼睛大不大,鼻子挺不挺,它不香嘛~
是什么
synchronized:Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。目的就是保证多个线程之间访问资源的同步性。
当然,synchronized是有发展阶段的,Java1.6之前,synchronized属于重量级锁,但在之后,在不断的优化过程中,如偏向锁、轻量级锁、自旋锁等技术来减少锁操作的开销。这一部分我们在接下来的系列文章慢慢讲~崩着急~先跟着姐姐一步步走~这一篇我们只讲最最基础的,并证明讲的是对滴
怎么用
synchronized关键字最主要的三种使用方式:
-
修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁
-
修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例
-
修饰代码块: 虽作用于某代码块上,但锁定的对象依旧是对象实例,同修饰实例方法
总结:
synchronized锁定的对象只有两种:1.类的实例 2.类对象(类锁)。当线程1访问同步静态方法时,是允许线程2同时访问该实例对象的同步非静态方法的。因为线程1和2占用的并不是同一把锁,并不会互斥
怎么证明我说的对呢
-
证明“修饰实例方法”和“修饰代码块”的锁定对象是一致的
public class SyncTest { public void test1() { //synchronized(this)锁定的是当前类的实例,这里锁定的是SyncTest类的实例 //synchronized(this) 效果等同于在方法上使用 synchronized synchronized (this) { System.out.println("t1 start"); try { for (int i = 1; i < 5; i++) { TimeUnit.SECONDS.sleep(i); System.out.println("t1 sleep " + i); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end"); } } public synchronized void test2() { System.out.println("t2 start"); System.out.println("t2 end"); } public static void main(String[] args) { SyncTest demo2 = new SyncTest(); //证明1 new Thread(demo2::test1).start(); new Thread(demo2::test2).start(); } }
-
证明“修饰实例方法”(修饰代码块)与“修饰静态方法”锁定对象不一致
public class SyncTest { public void test1() { //synchronized(this)锁定的是当前类的实例,这里锁定的是SyncTest类的实例 //synchronized(this) 效果等同于在方法上使用 synchronized synchronized (this) { System.out.println("t1 start"); try { for (int i = 1; i < 5; i++) { TimeUnit.SECONDS.sleep(i); System.out.println("t1 sleep " + i); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end"); } } public synchronized static void test3() { System.out.println("t3 start"); System.out.println("t3 end"); } public static void main(String[] args) { SyncTest demo2 = new SyncTest(); new Thread(demo2::test1).start(); new Thread(SyncTest::test3).start(); } }
‘饭后’甜点
-
可否以字符串常量作为锁定的对象——不可以
public class SyncTest2 { String s1 = "hello"; String s2 = "hello"; public void test1() { synchronized (s1) { System.out.println("t1 start..."); try { for (int i=1;i<5;i++){ TimeUnit.SECONDS.sleep(i); System.out.println("t1 sleep "+ i); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end..."); } } public void test2() { synchronized (s2) { System.out.println("t2 start..."); System.out.println("t2 end..."); } } public static void main(String[] args) { SyncTest2 demo = new SyncTest2(); new Thread(demo::test1, "test1").start(); new Thread(demo::test2, "test2").start(); } }
-
一个同步方法调用另外一个同步方法,能否得到锁?(重入锁的另外一种情况(继承))———可以
public class SyncTest3 { synchronized void test1(){ System.out.println("t1 start"); try { for (int i=1;i<5;i++){ TimeUnit.SECONDS.sleep(i); System.out.println("t1 sleep "+ i); } } catch (InterruptedException e) { e.printStackTrace(); } test2(); System.out.println("t1 end"); } synchronized void test2(){ System.out.println("t2 start"); System.out.println("t2 end"); } public static void main(String[] args) { SyncTest3 syncTest3=new SyncTest3(); syncTest3.test1(); } }
-
同步方法和非同步方法是否可以同时调用?——可以
public class SyncTest4 { public synchronized void test1() { System.out.println("t1 start"); try { for (int i=1;i<5;i++){ TimeUnit.SECONDS.sleep(i); System.out.println("t1 sleep "+ i); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end"); } public void test2() { System.out.println("t2 start"); System.out.println("t2 end"); } public static void main(String[] args) { SyncTest4 demo = new SyncTest4(); new Thread(demo::test1).start(); new Thread(demo::test2).start(); } }
Ending~
这只是synchronized初步应用,接下来我们将要一层层刨根问底儿~