同步方法跟同步方法块 synchronized

  • synchronized方法控制对象的访问,每个对象对应一把锁,每个synchronized方法都必须获得改方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占这把锁,知道方法结束才释放锁,后面被阻塞的线程才能获得这个锁被执行
  • synchronized关键字可以用在方法上标识锁住this对象
  • synchronized(Obj)方法块用在方法内 Obj是被锁的对象

 

代码示例1 模拟买票

 1 package 多线程练习.锁学习;
 2 
 3 public class 不安全线程买票实例 {
 4     public static void main(String[] args) {
 5         BuyTicket bt = new BuyTicket();
 6         new Thread(bt, "小明").start();
 7         new Thread(bt, "王老师").start();
 8         new Thread(bt, "黄牛党").start();
 9     }
10 }
11 
12 
13 /*
14    模拟一个买票的线程接口实现类
15  */
16 class BuyTicket implements Runnable {
17 
18     private int ticket = 10;
19     private Boolean flag = true;
20 
21     @Override
22     public void run() {
23         while (flag) {
24             buy();
25         }
26     }
27 
28     /*
29        买票方法
30      */
31     public synchronized void buy() {
32         // 票卖完了
33         if (ticket <= 0) {
34             flag = false;
35             return;
36         }
37 
38         // 模拟延时
39         try {
40             Thread.sleep(100);
41         } catch (InterruptedException e) {
42             e.printStackTrace();
43         }
44 
45         //模拟买票
46         System.out.println(Thread.currentThread().getName() + " 买到了第 " + ticket-- + " 张表");
47     }
48 }
View Code

输出结果

 

 

代码示例2 模拟银行取钱

 1 package 多线程练习.锁学习;
 2 
 3 import java.math.BigDecimal;
 4 
 5 /*
 6    模拟两个人同时取钱的情况
 7  */
 8 public class SafeAccount {
 9     public static void main(String[] args) {
10         Bank bank = new Bank("12345", new BigDecimal("100"));
11         WithDrawMoney xiaoming = new WithDrawMoney(bank, new BigDecimal("50"), "小明");
12         WithDrawMoney xiaomingxf = new WithDrawMoney(bank, new BigDecimal("100"), "小明媳妇");
13         xiaoming.start();
14         xiaomingxf.start();
15 
16     }
17 }
18 
19 
20 /*
21    银行类
22  */
23 class Bank {
24     String cardNumer;    // 卡号
25     BigDecimal balance;  // 余额  小tip:Java中用BigDecimal 来表示金钱类型
26 
27     public Bank(String cardNumer, BigDecimal balance) {
28         this.cardNumer = cardNumer;
29         this.balance = balance;
30     }
31 
32 }
33 
34 class WithDrawMoney extends Thread {
35     //  模拟正式环境全部私有
36     Bank bank;
37     BigDecimal nowMoney = new BigDecimal("0");   // 手里的钱
38     BigDecimal drawMoney;  // 取走的钱
39 
40     // 构造方法
41     public WithDrawMoney(Bank bank, BigDecimal drawMoney, String name) {
42         super(name);  // 调用父类的只能用在第一行
43         this.bank = bank;
44         this.drawMoney = drawMoney;
45     }
46 
47     @Override
48     public void run() {
49 
50         /*
51         synchronized 用在方法上面 则不需要在方法内加synchronized代码块  用在方法指定的是锁this对象 反射类。
52         synchronized 应当需要锁住的对象
53          */
54         synchronized (bank) {
55             if (bank.balance.subtract(drawMoney).compareTo(BigDecimal.ZERO) == -1) {
56                 System.out.println(this.getName() + " 钱不够了,取钱失败");  // 线程类中this.getName() ==  Thread.currentThread.getName()
57                 return;
58             }
59 
60             try {
61                 Thread.sleep(500);
62             } catch (InterruptedException e) {
63                 e.printStackTrace();
64             }
65 
66             nowMoney = nowMoney.add(drawMoney);                       // 手里的钱
67             bank.balance = (bank.balance.subtract(drawMoney));        // 卡上余额 subtract 减法  add 加法
68             System.out.println(this.getName() + " 手里有 " + nowMoney + "钱");
69             System.out.println("卡上余额:" + bank.balance);
70         }
71 
72     }
73 
74 
75 }
View Code

 

输出结果

 

 

 

代码示例3 容器

 1 package 多线程练习.锁学习;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 /*
 7   synchronized(Obj) 此处的 是锁住list对象
 8   Obj又称同步监视器
 9  */
10 public class SafeList {
11     public static void main(String[] args) {
12         List<String> list = new ArrayList<>();
13 
14         for (int i = 0; i < 10000; i++) {
15             new Thread(() -> {
16                 synchronized (list) {
17                     list.add(Thread.currentThread().getName());
18                 }
19             }).start();
20         }
21 
22         // Sleep就是为了扩大事情的发展面
23         try {
24             Thread.sleep(3000);
25         } catch (InterruptedException e) {
26             e.printStackTrace();
27         }
28 
29         System.out.println("数量为:" + list.size());
30 
31     }
32 }
View Code

 

输出结果

 

posted @ 2022-01-15 22:36  Chris丶Woo  阅读(24)  评论(0编辑  收藏  举报