同步解决线程安全问题的三种实现
/*
* 同步可以解决安全问题的根本原因就在那个对象上。
*
* 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文件(字节码文件)
*
*/
那么,我们到底使用谁?
如果锁对象是this,就可以考虑使用同步方法。
否则能使用同步代码块的尽量使用同步代码块。
示例代码如下:
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 }
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 }