2.1.4synchronized方法与锁对象
Posted 成功的路上总是离不开贵人的帮助,名师的指点和小人的刺激。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.1.4synchronized方法与锁对象相关的知识,希望对你有一定的参考价值。
为了证明线程锁的是对象
测试
1 package com.cky.bean; 2 3 /** 4 * Created by chenkaiyang on 2017/12/4. 5 */ 6 public class MyObject { 7 public void methodA () { 8 try { 9 System.out.println("begin methodA ThName=" +Thread.currentThread().getName()); 10 Thread.sleep(5000); 11 System.out.println("end"); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 } 16 }
1 package com.cky.thread; 2 3 import com.cky.bean.MyObject; 4 5 /** 6 * Created by chenkaiyang on 2017/12/4. 7 */ 8 public class ThreadA extends Thread{ 9 private MyObject mo; 10 public ThreadA (MyObject mo) { 11 this.mo = mo; 12 } 13 @Override 14 public void run() { 15 super.run(); 16 mo.methodA(); 17 } 18 }
package com.cky.thread; import com.cky.bean.MyObject; /** * Created by chenkaiyang on 2017/12/4. */ public class ThreadB extends Thread{ private MyObject mo; public ThreadB (MyObject mo) { this.mo = mo; } @Override public void run() { super.run(); mo.methodA(); } }
package com.cky.test; import com.cky.bean.MyObject; import com.cky.thread.ThreadA; import com.cky.thread.ThreadB; /** * Created by chenkaiyang on 2017/12/2. */ public class Test { public static void main(String[] args){ MyObject myObject = new MyObject(); ThreadA threadA = new ThreadA(myObject); threadA.setName("A"); ThreadB threadB = new ThreadB(myObject); threadB.setName("B"); threadA.start(); threadB.start(); } }
D:\it\jdk1.8\bin\java -Didea.launcher.port=7533 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test begin methodA ThName=A begin methodA ThName=B end end
结果如上分析,代码调用是异步随机执行。
然后在方法中加同步关键字
package com.cky.bean; /** * Created by chenkaiyang on 2017/12/4. */ public class MyObject { synchronized public void methodA () { try { System.out.println("begin methodA ThName=" +Thread.currentThread().getName()); Thread.sleep(5000); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }
D:\it\jdk1.8\bin\java -Didea.launcher.port=7534 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test begin methodA ThName=A end begin methodA ThName=B end
结果分析:
调用关键字synchronized声明的方法一定是排队运行的,只有共享的资源才需要同步,如果不是共享的资源,根本没有必要同步。
那如果其他的方法被调用会有什么效果。
测试
继续更改MyObject
package com.cky.bean; /** * Created by chenkaiyang on 2017/12/4. */ public class MyObject { synchronized public void methodA () { try { System.out.println("begin methodA ThName=" +Thread.currentThread().getName()); Thread.sleep(5000); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } public void methodB() { try { System.out.println("begin methodB ThName=" +Thread.currentThread().getName()); Thread.sleep(5000); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.cky.thread; import com.cky.bean.MyObject; /** * Created by chenkaiyang on 2017/12/4. */ public class ThreadA extends Thread{ private MyObject mo; public ThreadA (MyObject mo) { this.mo = mo; } @Override public void run() { super.run(); mo.methodA(); } }
package com.cky.thread; import com.cky.bean.MyObject; /** * Created by chenkaiyang on 2017/12/4. */ public class ThreadB extends Thread{ private MyObject mo; public ThreadB (MyObject mo) { this.mo = mo; } @Override public void run() { super.run(); mo.methodB(); } }
package com.cky.test; import com.cky.bean.MyObject; import com.cky.thread.ThreadA; import com.cky.thread.ThreadB; /** * Created by chenkaiyang on 2017/12/2. */ public class Test { public static void main(String[] args){ MyObject myObject = new MyObject(); ThreadA threadA = new ThreadA(myObject); threadA.setName("A"); ThreadB threadB = new ThreadB(myObject); threadB.setName("B"); threadA.start(); threadB.start(); } }
D:\it\jdk1.8\bin\java -Didea.launcher.port=7536 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test begin methodA ThName=A begin methodB ThName=B end end
结果分析:虽然线程A先持有object对象的锁,但是线程B完全可以异步调用非synchronized类型的方法。
继续再methodB方法上加上synchronized
package com.cky.bean; /** * Created by chenkaiyang on 2017/12/4. */ public class MyObject { synchronized public void methodA () { try { System.out.println("begin methodA ThName=" +Thread.currentThread().getName()); Thread.sleep(5000); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public void methodB() { try { System.out.println("begin methodB ThName=" +Thread.currentThread().getName()); Thread.sleep(5000); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }
D:\it\jdk1.8\bin\java -Didea.launcher.port=7537 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test begin methodB ThName=B end begin methodA ThName=A end Process finished with exit code 0
结果分析:
1)A线程先持有对象锁,B线程可以异步方法调用object对象中非同步的方法
2)A线程先持有对象锁,B线程此时如果想要调用B线程中其他的同步方法,则需要等待A线程释放才行
以上是关于2.1.4synchronized方法与锁对象的主要内容,如果未能解决你的问题,请参考以下文章