前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >同步解决线程安全问题的三种实现

同步解决线程安全问题的三种实现

作者头像
黑泽君
发布2018-10-11 11:40:46
3700
发布2018-10-11 11:40:46
举报
文章被收录于专栏:黑泽君的专栏黑泽君的专栏

同步解决线程安全问题的三种实现

代码语言:javascript
复制
/*
 * 同步可以解决安全问题的根本原因就在那个对象上。
 * 
 * A:同步代码块的格式及其锁对象问题?
 *         格式:
 *         synchronized (对象名称) {
 *             需要同步的代码;
 *         }
 * 
 *         同步代码块的锁对象是谁呢?
 *             任意对象。
 * 
 * B:同步方法的格式及其锁对象问题?
 *         如果一个方法一进去就看到了代码被同步了,那么我就在想能不能把这个同步加在方法上呢? 答:能。
 *         把同步关键字加在方法上。
 *         格式:
 *         synchronized private void sellTicket() {...}
 *         private synchronized void sellTicket() {...}    // 习惯上这样写
 * 
 *         同步方法的锁对象是谁呢?(方法的内部有一个你看不到的对象是this啊,傻瓜哈)
 *             this
 * 
 * C:静态同步方法的格式及其锁对象问题?
 *         格式:
 *         private static synchronized void sellTicket() {...}
 *         
 *         静态同步方法的锁对象是谁呢?
 *             当前类的字节码文件对象。(反射会讲)
 * 
 *         类的初始化过程:Person p = new Person(); // 第一步做的事情是:把Person.class文件加载进内存。在Person.class文件中找到main方法并放到栈。
 *         因为静态是随着类的加载而加载。此时对象this根本就不存在。此时的对象是.class文件(字节码文件)。
 * 
 *         简言之:要想同步,需要先确定同步的对象。
 *                 要在静态同步方法加载之前就得先确定同步的对象,(否则你跟我咋同步)
 *                     谁比静态先存在呢? 答:只有.class文件(字节码文件)
 *         
 */
代码语言:javascript
复制
那么,我们到底使用谁?
  如果锁对象是this,就可以考虑使用同步方法。
  否则能使用同步代码块的尽量使用同步代码块。

示例代码如下:

代码语言:javascript
复制
 1 package cn.itcast_11;
 2 
 3 /*
 4  * 同步可以解决安全问题的根本原因就在那个对象上。
 5  * 
 6  * A:同步代码块的格式及其锁对象是谁呢?
 7  *         格式:
 8  *         synchronized (对象名称) {
 9  *             需要同步的代码;
10  *         }
11  * 
12  *         同步代码块的锁对象是谁呢?
13  *             任意对象。
14  * 
15  * B:同步方法的格式及其锁对象问题?
16  *         如果一个方法一进去就看到了代码被同步了,那么我就在想能不能把这个同步加在方法上呢? 答:能。
17  *         把同步关键字加在方法上。
18  *         格式:
19  *         synchronized private void sellTicket() {...}
20  *         private synchronized void sellTicket() {...}    // 习惯上这样写
21  * 
22  *         同步方法的锁对象是谁呢?(方法的内部有一个你看不到的对象是this啊,傻瓜哈)
23  *             this
24  * 
25  * C:静态同步方法的格式及其锁对象问题?
26  *         格式:
27  *         private static synchronized void sellTicket() {...}
28  *         
29  *         静态同步方法的锁对象是谁呢?
30  *             当前类的字节码文件对象。(反射会讲)
31  * 
32  *         类的初始化过程:Person p = new Person(); // 第一步做的事情是:把Person.class文件加载进内存。在Person.class文件中找到main方法并放到栈。
33  *         因为静态是随着类的加载而加载。此时对象this根本就不存在。此时的对象是.class文件(字节码文件)。
34  * 
35  *         简言之:要想同步,需要先确定同步的对象。
36  *                 要在静态同步方法加载之前就得先确定同步的对象,(否则你跟我咋同步)
37  *                     谁比静态先存在呢? 答:只有.class文件(字节码文件)
38  *         
39  */
40 public class SellTicketDemo {
41     public static void main(String[] args) {
42         // 创建资源对象
43         SellTicket st = new SellTicket();
44 
45         // 创建三个线程对象
46         Thread t1 = new Thread(st, "窗口1");
47         Thread t2 = new Thread(st, "窗口2");
48         Thread t3 = new Thread(st, "窗口3");
49 
50         // 启动线程
51         t1.start();
52         t2.start();
53         t3.start();
54     }
55 }
代码语言:javascript
复制
  1 package cn.itcast_11;
  2 
  3 public class SellTicket implements Runnable {
  4 
  5     // 定义100张票
  6     private static int tickets = 100;
  7 
  8     // 定义同一把锁为obj对象
  9     private Object obj = new Object();
 10     
 11     // 定义同一把锁为任意对象
 12     private Demo d = new Demo();
 13 
 14     private int x = 0;
 15     
 16     /*
 17     // 同步代码块用obj对象做锁
 18     @Override
 19     public void run() {
 20         while (true) {
 21             synchronized (obj) {
 22                 if (tickets > 0) {
 23                     try {
 24                         Thread.sleep(100);
 25                     } catch (InterruptedException e) {
 26                         e.printStackTrace();
 27                     }
 28                     System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
 29                 }
 30             }
 31         }
 32     }
 33     */
 34     
 35     /*
 36     // 同步代码块用任意对象做锁
 37     @Override
 38     public void run() {
 39         while (true) {
 40             synchronized (d) {
 41                 if (tickets > 0) {
 42                     try {
 43                         Thread.sleep(100);
 44                     } catch (InterruptedException e) {
 45                         e.printStackTrace();
 46                     }
 47                     System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
 48                 }
 49             }
 50         }
 51     }
 52     */
 53     
 54     @Override
 55     public void run() {
 56         while (true) {
 57             if (x % 2 == 0) {
 58                 synchronized (SellTicket.class) {
 59                     if (tickets > 0) {
 60                         try {
 61                             Thread.sleep(100);
 62                         } catch (InterruptedException e) {
 63                             e.printStackTrace();
 64                         }
 65                         System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
 66                     }
 67                 }
 68             } else {
 69                 /*
 70                 synchronized (d) {
 71                     if (tickets > 0) {
 72                         try {
 73                             Thread.sleep(100);
 74                         } catch (InterruptedException e) {
 75                             e.printStackTrace();
 76                         }
 77                         System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
 78                     }
 79                 }
 80                 */
 81                 sellTicket();    
 82             }
 83             x++;
 84         }
 85     }
 86     
 87 
 88     /*
 89     private void sellTicket() {
 90         synchronized (d) {
 91             if (tickets > 0) {
 92                 try {
 93                     Thread.sleep(100);
 94                 } catch (InterruptedException e) {
 95                     e.printStackTrace();
 96                 }
 97                 System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
 98             }
 99         }
100     }
101      */
102     
103     /*
104     // 如果一个方法一进去就看到了代码被同步了,那么我就在想能不能把这个同步加在方法上呢? 答:能。
105     // 同步方法
106     private synchronized void sellTicket() {
107         if (tickets > 0) {
108             try {
109                 Thread.sleep(100);
110             } catch (InterruptedException e) {
111                 e.printStackTrace();
112             }
113             System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
114         }
115     }
116      */
117     
118     // 静态同步方法
119     private static synchronized void sellTicket() {
120         if (tickets > 0) {
121             try {
122                 Thread.sleep(100);
123             } catch (InterruptedException e) {
124                 e.printStackTrace();
125             }
126             System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
127         }
128     }
129     
130 }
131 
132 class Demo {
133 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档