关键词搜索

源码搜索 ×
×

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

发布2018-06-11浏览15675次

详情内容

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、总结

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载