经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
java基础Synchronized关键字之对象锁
来源:cnblogs  作者:小墨di  时间:2018/11/5 11:13:40  对本文有异议

java中Synchronized关键字之对象锁

    当有多个线程对一个共享数据进行操作时,需要注意多线程的安全问题。

  多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。而用的最多的就是synchronized关键字。

  语法:Synchronized(对象锁){}

  被synchronized关键字修饰的一个方法,则这个方法叫做同步方法

  当synchronized方法执行完或发生异常时,会自动释放锁。


 1.是否使用synchronized关键字的不同


 

  1. package threadDemo;
  2. public class ThreadDemo
  3. {
  4. public static void main(String[] args)
  5. {
  6. Example example = new Example();
  7. Thread t1 = new TH(example);
  8. Thread t2 = new TH(example);
  9. t1.start();
  10. t2.start();
  11. }
  12. }
  13. class Example
  14. {
  15. public synchronized void show()
  16. {
  17. for (int i = 0; i < 10; ++i)
  18. {
  19. try
  20. {
  21. Thread.sleep(500);
  22. }
  23. catch (InterruptedException e)
  24. {
  25. e.printStackTrace();
  26. }
  27. System.out.println(i);
  28. }
  29. }
  30. }
  31. class TH extends Thread
  32. {
  33. private Example example;
  34. public TH(Example example)
  35. {
  36. this.example = example;
  37. }
  38. @Override
  39. public void run()
  40. {
  41. example.show();
  42. }
  43. }

运行结果:

  1. show()0
  2. show()1
  3. show()2
  4. show()3
  5. show()4
  6. show()5
  7. show()6
  8. show()7
  9. show()8
  10. show()9
  11. show2()0
  12. show2()1
  13. show2()2
  14. show2()3
  15. show2()4
  16. show2()5
  17. show2()6
  18. show2()7
  19. show2()8
  20. show2()9

 

是否在show()方法前加上synchronized关键字,这个例子程序的执行结果会有很大的不同。

  如果不加synchronized关键字,则两个线程同时执行show()方法,输出是两组并发的。

  如果加上synchronized关键字,则会先输出一组0到9,然后再输出下一组,说明两个线程是顺次执行的。


 2.同步方法的锁是this


 

在静态同步方法中的对象锁是这个类的字节码文件对象。类.class

要想获取一个类的字节码文件对象,有两种方法

1通过当前类.class

2通过当前类的实例对象.getClass()方法获取

 

  1. public class ClassDemo {
  2. void show(){
  3. //任何一个类可以通过.class来获取字节码文件对象
  4. Class<ClassDemo> c = ClassDemo.class;
  5. //任何一个对象可以通过getClass()方法来获取字节码文件对象
  6. Class<? extends ClassDemo> class1 = new ClassDemo().getClass();
  7. }
  8. }

 

验证同步方法的对象锁是this

  思路:

  启动两个线程,让一个线程进入同步代码块,一个线程进入同步方法

  用到了一个中间的控制变量boolean flag

  线程对象的run中,实现三个窗口出售100张票的功能,让程序进入一个同步代码块中,并且在线程对象中,再定义一个同步方法,功能与同步代码块中的功能相同。

 

package threadDemo;

public class ThreadDemo03 {


public static void main(String[] args) {
T t = new T();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);

t1.start();
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
t.flag=false;
t2.start();
}

}

class T implements Runnable {
private int ticket = 100;
boolean flag = true;
Object obj = new Object();

@Override
public void run() {
if (flag) {
while (true) {
//synchronized (this) {
synchronized (obj){
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
}
}

}
}else{
while(true){
show();
}
}

}

public synchronized void show(){//synchronized (this)
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
}
}

}

运行结果:

  1. Thread-0正在出售第100张票
  2. Thread-1正在出售第99张票
  3. Thread-0正在出售第98张票
  4. Thread-1正在出售第97张票
  5. Thread-0正在出售第96张票
  6. Thread-1正在出售第95张票
  7. Thread-0正在出售第94张票
  8. Thread-1正在出售第93张票
  9. Thread-0正在出售第92张票
  10. Thread-1正在出售第91张票
  11. Thread-0正在出售第90张票
  12. Thread-1正在出售第89张票
  13. Thread-0正在出售第88张票
  14. Thread-1正在出售第87张票
  15. Thread-0正在出售第86张票
  16. Thread-1正在出售第85张票
  17. Thread-0正在出售第84张票
  18. Thread-1正在出售第83张票
  19. Thread-0正在出售第82张票
  20. Thread-1正在出售第81张票
  21. Thread-0正在出售第80张票
  22. Thread-1正在出售第79张票
  23. Thread-0正在出售第78张票
  24. Thread-1正在出售第77张票
  25. Thread-0正在出售第76张票
  26. Thread-1正在出售第75张票
  27. Thread-0正在出售第74张票
  28. Thread-1正在出售第73张票
  29. Thread-0正在出售第72张票
  30. Thread-1正在出售第71张票
  31. Thread-0正在出售第71张票
  32. Thread-1正在出售第70张票
  33. Thread-0正在出售第69张票
  34. Thread-1正在出售第68张票
  35. Thread-0正在出售第68张票
  36. Thread-1正在出售第66张票
  37. Thread-0正在出售第67张票
  38. Thread-1正在出售第65张票
  39. Thread-0正在出售第65张票
  40. Thread-0正在出售第64张票
  41. Thread-1正在出售第63张票
  42. Thread-0正在出售第62张票
  43. Thread-1正在出售第61张票
  44. Thread-1正在出售第60张票
  45. Thread-0正在出售第59张票
  46. Thread-0正在出售第58张票
  47. Thread-1正在出售第57张票
  48. Thread-1正在出售第56张票
  49. Thread-0正在出售第55张票
  50. Thread-1正在出售第54张票
  51. Thread-0正在出售第54张票
  52. Thread-1正在出售第53张票
  53. Thread-0正在出售第52张票
  54. Thread-1正在出售第51张票
  55. Thread-0正在出售第50张票
  56. Thread-0正在出售第49张票
  57. Thread-1正在出售第48张票
  58. Thread-0正在出售第47张票
  59. Thread-1正在出售第47张票
  60. Thread-1正在出售第46张票
  61. Thread-0正在出售第45张票
  62. Thread-1正在出售第44张票
  63. Thread-0正在出售第43张票
  64. Thread-0正在出售第42张票
  65. Thread-1正在出售第41张票
  66. Thread-0正在出售第40张票
  67. Thread-1正在出售第39张票
  68. Thread-0正在出售第38张票
  69. Thread-1正在出售第37张票
  70. Thread-0正在出售第36张票
  71. Thread-1正在出售第35张票
  72. Thread-0正在出售第34张票
  73. Thread-1正在出售第33张票
  74. Thread-0正在出售第32张票
  75. Thread-1正在出售第31张票
  76. Thread-0正在出售第30张票
  77. Thread-1正在出售第29张票
  78. Thread-0正在出售第28张票
  79. Thread-1正在出售第27张票
  80. Thread-0正在出售第26张票
  81. Thread-1正在出售第25张票
  82. Thread-0正在出售第24张票
  83. Thread-1正在出售第23张票
  84. Thread-0正在出售第22张票
  85. Thread-1正在出售第21张票
  86. Thread-0正在出售第20张票
  87. Thread-1正在出售第19张票
  88. Thread-0正在出售第18张票
  89. Thread-1正在出售第17张票
  90. Thread-0正在出售第16张票
  91. Thread-1正在出售第15张票
  92. Thread-0正在出售第14张票
  93. Thread-1正在出售第13张票
  94. Thread-0正在出售第12张票
  95. Thread-1正在出售第11张票
  96. Thread-0正在出售第10张票
  97. Thread-1正在出售第9张票
  98. Thread-0正在出售第8张票
  99. Thread-1正在出售第7张票
  100. Thread-0正在出售第6张票
  101. Thread-1正在出售第5张票
  102. Thread-0正在出售第4张票
  103. Thread-1正在出售第3张票
  104. Thread-0正在出售第2张票
  105. Thread-1正在出售第1张票
  106. Thread-0正在出售第0张票

 

通过改变class T中同步代码块synchronized (对象锁) 的对象锁obj改成this依然成立。所以同步方法的对象锁是this。

其中public synchronized void show()就相当于synchronized (this)

静态同步方法的对象锁是类的字节码文件对象 类.class | 对象.getClass()

 

  1. package threadDemo;
  2. public class ThreadDemo2 {
  3. /*
  4. * 通过验证发现同步函数,如果被静态修饰后,不再以this为锁静态进内存时,内存中没有本类的对象,
  5. * 但一定有该类的字节码文件对象 类名.class
  6. * 该对象的类型是class 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
  7. */
  8. public static void main(String[] args) {
  9. Ticket t = new Ticket();
  10. Thread t1 = new Thread(t);
  11. Thread t2 = new Thread(t);
  12. // 开启第一个线程 但不一定马上执行
  13. t1.start();
  14. t.flag = false;// 改变标志
  15. try {
  16. Thread.sleep(50);
  17. } catch (Exception e) {
  18. } // 让主线程睡眠50毫秒 保证第一个线程先开始运行 且标志位改变
  19. t2.start();
  20. }
  21. }
  22. class Ticket implements Runnable {
  23. private static int ticket = 100;
  24. boolean flag = true;
  25. public void run() {
  26. if (flag) {
  27. while (true) {
  28. // synchronized(this)
  29. synchronized (Ticket.class) {
  30. if (ticket > 0) {
  31. try {
  32. Thread.sleep(50);
  33. } catch (Exception e) {
  34. }
  35. System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
  36. }
  37. }
  38. }
  39. } else
  40. while (true)
  41. show();
  42. }
  43. // 静态同步函数 该类对应的字节码文件对象为锁
  44. public static synchronized void show(){//synchronized (this)
  45. if (ticket > 0) {
  46. try {
  47. Thread.sleep(50);
  48. } catch (Exception e) {
  49. }
  50. System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
  51. }
  52. }
  53. }

运行结果:

  1. Thread-0正在出售第100张票
  2. Thread-0正在出售第99张票
  3. Thread-0正在出售第98张票
  4. Thread-0正在出售第97张票
  5. Thread-0正在出售第96张票
  6. Thread-0正在出售第95张票
  7. Thread-0正在出售第94张票
  8. Thread-0正在出售第93张票
  9. Thread-0正在出售第92张票
  10. Thread-0正在出售第91张票
  11. Thread-1正在出售第90张票
  12. Thread-1正在出售第89张票
  13. Thread-1正在出售第88张票
  14. Thread-0正在出售第87张票
  15. Thread-1正在出售第86张票
  16. Thread-1正在出售第85张票
  17. Thread-0正在出售第84张票
  18. Thread-0正在出售第83张票
  19. Thread-1正在出售第82张票
  20. Thread-1正在出售第81张票
  21. Thread-0正在出售第80张票
  22. Thread-0正在出售第79张票
  23. Thread-1正在出售第78张票
  24. Thread-0正在出售第77张票
  25. Thread-1正在出售第76张票
  26. Thread-1正在出售第75张票
  27. Thread-1正在出售第74张票
  28. Thread-0正在出售第73张票
  29. Thread-0正在出售第72张票
  30. Thread-1正在出售第71张票
  31. Thread-1正在出售第70张票
  32. Thread-1正在出售第69张票
  33. Thread-0正在出售第68张票
  34. Thread-1正在出售第67张票
  35. Thread-0正在出售第66张票
  36. Thread-0正在出售第65张票
  37. Thread-0正在出售第64张票
  38. Thread-0正在出售第63张票
  39. Thread-0正在出售第62张票
  40. Thread-1正在出售第61张票
  41. Thread-1正在出售第60张票
  42. Thread-1正在出售第59张票
  43. Thread-0正在出售第58张票
  44. Thread-0正在出售第57张票
  45. Thread-0正在出售第56张票
  46. Thread-0正在出售第55张票
  47. Thread-0正在出售第54张票
  48. Thread-0正在出售第53张票
  49. Thread-0正在出售第52张票
  50. Thread-0正在出售第51张票
  51. Thread-1正在出售第50张票
  52. Thread-1正在出售第49张票
  53. Thread-0正在出售第48张票
  54. Thread-0正在出售第47张票
  55. Thread-0正在出售第46张票
  56. Thread-0正在出售第45张票
  57. Thread-0正在出售第44张票
  58. Thread-1正在出售第43张票
  59. Thread-1正在出售第42张票
  60. Thread-0正在出售第41张票
  61. Thread-1正在出售第40张票
  62. Thread-0正在出售第39张票
  63. Thread-0正在出售第38张票
  64. Thread-0正在出售第37张票
  65. Thread-0正在出售第36张票
  66. Thread-0正在出售第35张票
  67. Thread-0正在出售第34张票
  68. Thread-0正在出售第33张票
  69. Thread-0正在出售第32张票
  70. Thread-1正在出售第31张票
  71. Thread-1正在出售第30张票
  72. Thread-1正在出售第29张票
  73. Thread-1正在出售第28张票
  74. Thread-1正在出售第27张票
  75. Thread-1正在出售第26张票
  76. Thread-1正在出售第25张票
  77. Thread-1正在出售第24张票
  78. Thread-0正在出售第23张票
  79. Thread-0正在出售第22张票
  80. Thread-0正在出售第21张票
  81. Thread-1正在出售第20张票
  82. Thread-0正在出售第19张票
  83. Thread-0正在出售第18张票
  84. Thread-0正在出售第17张票
  85. Thread-1正在出售第16张票
  86. Thread-1正在出售第15张票
  87. Thread-1正在出售第14张票
  88. Thread-1正在出售第13张票
  89. Thread-0正在出售第12张票
  90. Thread-1正在出售第11张票
  91. Thread-0正在出售第10张票
  92. Thread-0正在出售第9张票
  93. Thread-0正在出售第8张票
  94. Thread-1正在出售第7张票
  95. Thread-0正在出售第6张票
  96. Thread-0正在出售第5张票
  97. Thread-0正在出售第4张票
  98. Thread-1正在出售第3张票
  99. Thread-1正在出售第2张票
  100. Thread-0正在出售第1张票

 

 

 

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号