java之Synchronized(锁住对象和锁住代码)

举报
chenyu 发表于 2021/07/27 01:17:02 2021/07/27
【摘要】 1、问题 Synchronized我们一般都知道是锁,但是我们怎么区分是锁对象还是锁代码呢?   2、测试Demo package leetcode.chenyu.test; public class Synchronized { class Test { public synchronized void testFirst() { print...

1、问题

Synchronized我们一般都知道是锁,但是我们怎么区分是锁对象还是锁代码呢?

 


2、测试Demo


  
  1. package leetcode.chenyu.test;
  2. public class Synchronized {
  3. class Test {
  4. public synchronized void testFirst() {
  5. print("testFirst");
  6. }
  7. public void testSecond() {
  8. synchronized(this) {
  9. print("testSecond");
  10. }
  11. }
  12. public void testThird() {
  13. synchronized(Test.class) {
  14. print("testThird");
  15. }
  16. }
  17. public void print(String method) {
  18. System.out.println(method + "start");
  19. try {
  20. Thread.sleep(100);
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. System.out.println(method + "end");
  25. }
  26. }
  27. class TestThread extends Thread {
  28. public int mType = 0;
  29. public Test mTest = null;
  30. public TestThread(int type, Test test) {
  31. this.mType = type;
  32. this.mTest = test;
  33. }
  34. public void run() {
  35. if (mTest == null) {
  36. if (mType == 1) {
  37. Test test = new Test();
  38. test.testFirst();
  39. }
  40. else if (mType == 2) {
  41. Test test = new Test();
  42. test.testSecond();
  43. }
  44. else if (mType == 3) {
  45. Test test = new Test();
  46. test.testThird();
  47. }
  48. } else {
  49. if (mType == 1) {
  50. mTest.testFirst();
  51. }
  52. else if (mType == 2) {
  53. mTest.testSecond();
  54. }
  55. else if (mType == 3) {
  56. mTest.testThird();
  57. }
  58. }
  59. }
  60. }
  61. public static void main(String[] args) {
  62. Synchronized syn = new Synchronized();
  63. Test test = syn.new Test();
  64. for (int i = 0; i < 5; ++i) {
  65. syn.new TestThread(1, null).start();
  66. }
  67. }
  68. }

 


3、运行结果和分析

 

1)、按照上面的运行结果


  
  1. testFirststart
  2. testFirststart
  3. testFirststart
  4. testFirststart
  5. testFirststart
  6. testFirstend
  7. testFirstend
  8. testFirstend
  9. testFirstend
  10. testFirstend

 

2)、把for循环里面的代码换如下

 

syn.new TestThread(2, null).start();
 

运行结果如下


  
  1. testSecondstart
  2. testSecondstart
  3. testSecondstart
  4. testSecondstart
  5. testSecondstart
  6. testSecondend
  7. testSecondend
  8. testSecondend
  9. testSecondend
  10. testSecondend

对于上面1)、2)、两种情况,synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段,锁的是对象,也就是锁的本身this, 由于每个线程都新构建了一个新的对象,所以加了synchronized没有锁住。

 

3)、把for循环里面的代码换如下

syn.new TestThread(1, test).start();
 
syn.new TestThread(2, test).start();
 

运行结果都一样如下


  
  1. testSecondstart
  2. testSecondend
  3. testSecondstart
  4. testSecondend
  5. testSecondstart
  6. testSecondend
  7. testSecondstart
  8. testSecondend
  9. testSecondstart
  10. testSecondend

这里由于我们几个现场都共用一个对象,所以对象固定了,所以就锁住了,其它线程在没有释放锁的时候,进不来。

4)、把for循环里面的代码换如下

syn.new TestThread(3, null).start();

 
syn.new TestThread(3, test).start();
 

结果都如下


  
  1. testThirdstart
  2. testThirdend
  3. testThirdstart
  4. testThirdend
  5. testThirdstart
  6. testThirdend
  7. testThirdstart
  8. testThirdend
  9. testThirdstart
  10. testThirdend

synchronized(Test.class)实现了全局锁的效果,不管对象是不是一样的,都是同样的效果,就锁住代码了

 

我么一般用这个比较多。

 

 

 

 

4、总结

1、synchronized加在非静态方法前和synchronized(this)都是锁住了这个类的对象,如果多线程访问,对象不同,就锁不住,对象固定是一个,就可锁住。

2、synchronized(类名.class)和加在静态方法前,是锁住了代码块,不管多线程访问的时候对象是不是同一个,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步,缩小锁的粒度。

 

 

 

 

 

 

 


4、总结

文章来源: chenyu.blog.csdn.net,作者:chen.yu,版权归原作者所有,如需转载,请联系作者。

原文链接:chenyu.blog.csdn.net/article/details/80646679

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。