Java线程安全之同步方法

打印 上一主题 下一主题

主题 567|帖子 567|积分 1701

同步方法

使用synchronized修饰的方法,就叫做同步方法,其固定格式如下:
  1. public [static] synchronized 返回值类型 同步方法() {
  2.         可能会产生线程安全问题的代码
  3. }
复制代码
留意事项:


  • 同步方法可以是平凡成员方法,也可以是static静态方法
  • 平凡成员同步方法,默认锁对象为this,即当火线法的调用对象
  • static静态同步方法,默认锁对象是当前类的字节码对象(一个类有且只有一个)
   类的字节码对象:类名.class,固定用法(当前记取即可,后续反射章节会学习)
  案例1:平凡同步方法
​ 创建子线程1,调用100次平凡方法print1(逐字输出 “好好学习”)
​ 创建子线程2,调用100次平凡方法print2(逐字输出 “天天向上”)
​ 要求,两个子线程在执行方法的过程中,不会被另一个线程打断。
  1. class Printer {
  2.         //普通同步方法: 锁对象默认为this
  3.         public synchronized void print1() {
  4.                 System.out.print("天");
  5.                 System.out.print("天");
  6.                 System.out.print("向");
  7.                 System.out.print("上");
  8.                 System.out.println();
  9.         }
  10.        
  11.         public void print2() {       
  12.         //同步代码块,也使用this作为锁对象
  13.         //测试时,可以注释同步代码块,或使用其他锁对象,然后观察程序运行效果
  14.                 //synchronized (Printer.class) {
  15.         synchronized (this) {
  16.                         System.out.print("努");
  17.                         System.out.print("力");
  18.                         System.out.print("学");
  19.                         System.out.print("习");
  20.                         System.out.println();
  21.                 }
  22.         }
  23. }
  24. public class Test16_Funtion {
  25.         public static void main(String[] args) {
  26.                 //准备一个对象
  27.                 final Printer p = new Printer();
  28.                
  29.                 //创建子线程1,输出100次 "好好学习"
  30.                 Thread th1 = new Thread() {
  31.                         @Override
  32.                         public void run() {
  33.                                 for(int i = 0; i < 100; i++)
  34.                                         p.print1();
  35.                         }
  36.                 };
  37.                
  38.                 //创建子线程2,输出100次 "天天向上"
  39.                 Thread th2 = new Thread() {
  40.                         @Override
  41.                         public void run() {
  42.                                 for(int i = 0; i < 100; i++)
  43.                                         p.print2();
  44.                         }
  45.                 };
  46.                
  47.                 th1.start();
  48.                 th2.start();
  49.         }
  50. }
复制代码
测试结果:


  • print2方法不使用同步代码块,或不使用this作为锁对象,会出现输出杂乱的情况,线程没有实现同步(上锁失败)



  • print2方法使用同步代码块,且用this作为锁对象,成功实现线程同步

案例2:静态同步方法
​ 将上述案例中的平凡同步方法,修改为静态同步方法,实现原有功能。
  1. class Printer {
  2.     // ...省略print1() print2()
  3.    
  4.         //static静态同步方法: 锁对象默认为当前类字节码对象
  5.         public static synchronized void print3() {
  6.                 System.out.print("天");
  7.                 System.out.print("天");
  8.                 System.out.print("向");
  9.                 System.out.print("上");
  10.                 System.out.println();
  11.         }
  12.        
  13.         public void print4() {       
  14.         //同步代码块,使用当前类字节码对象作为锁对象
  15.         
  16.         //注释掉同步代码块,运行测试,观察效果
  17.         //不使用当前类字节码对象作为锁对象,运行测试,观察效果
  18.         //synchronized (this) {
  19.                 synchronized (Printer.class) {
  20.                         System.out.print("努");
  21.                         System.out.print("力");
  22.                         System.out.print("学");
  23.                         System.out.print("习");
  24.                         System.out.println();
  25.                 }
  26.         }
  27. }
  28. public class Test16_Funtion {
  29.         public static void main(String[] args) {
  30.                 //准备一个对象
  31.                 final Printer p = new Printer();
  32.                
  33.                 //创建子线程1,输出100次 "好好学习"
  34.                 Thread th1 = new Thread() {
  35.                         @Override
  36.                         public void run() {
  37.                                 for(int i = 0; i < 100; i++)
  38.                                         Printer.print3();
  39.                         }
  40.                 };
  41.                
  42.                 //创建子线程2,输出100次 "天天向上"
  43.                 Thread th2 = new Thread() {
  44.                         @Override
  45.                         public void run() {
  46.                                 for(int i = 0; i < 100; i++)
  47.                                         p.print4();
  48.                         }
  49.                 };
  50.                
  51.                 th1.start();
  52.                 th2.start();
  53.         }
  54. }
复制代码
运行测试:
​ 按照print4方法中形貌进行测试,验证结论:
   static静态同步方法: 锁对象默认为当前类字节码对象(类名.class)
  线程状态图为:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表