线程同步(排队)

线程同步发生在多个线程操作同一个资源时

并发:同一个对象被多个线程同时操作(可参考前面买火车票和龟兔赛跑的例子)

 

处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象,此时就需要线程同步,线程同步是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面的线程使用完毕,下一个线程再使用

 

队列和锁(线程同步的形成条件)

形象一点,下面的文字可以结合生活中公共厕所来理解 

由于同一个进程的多个线程共享同一块存储空间(公共厕所),在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入了锁机制synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可(用时关门,用完开门),存在以下问题:

  ①一个线程持有锁会导致其他有需要此锁的线程挂起(等待

  ②在多线程竞争下,加锁,释放锁会导致较多的上下文切换和调度延时,引起性能问题(进进出出

  ③如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题(使用时间的长短

 

线程同步的实现

  ①在方法前添加synchronized关键字,让该方法成为同步方法,锁的是this(如果将一个很复杂的方法变为同步方法,会影响效率)

  ②同步块:synchronized(共享资源作为对象){}

 线程同步(排队)

 

 

 1 public class Bank {
 2     public static void main(String[] args) {
 3         Account account = new Account(500, "结婚基金");
 4         Get you = new Get(account, 300, "你");
 5         Get youGf = new Get(account, 500, "你女朋友");
 6         you.start();
 7         youGf.start();
 8     }
 9 }
10 
11 //账户
12 class Account {
13     int money;
14     String cdName;//卡号
15 
16     public Account(int money, String name) {
17         this.money = money;
18         cdName = name;
19     }
20 }
21 
22 //模拟银行取钱
23 class Get extends Thread {
24     Account account;
25     int getMoney;//取多少钱
26     String Name;//取钱的是人
27 
28     public Get(Account account, int getMoney, String Name) {
29         this.account = account;
30         this.getMoney = getMoney;
31         this.Name = Name;
32     }
33 
34     @Override
35     public void run() {
36      //同步块 
37         synchronized (account) {
38             if (account.money - getMoney < 0) {
39                 System.out.println(Name + "取的时候,余额不足");
40                 return;
41             }
42 
43             try {
44                 Thread.sleep(1000);
45             } catch (InterruptedException e) {
46                 e.printStackTrace();
47             }
48             //余额
49             account.money = account.money - getMoney;
50 
51             System.out.println(Name + "取后," + "卡里的钱为" + account.money);
52         }
53 
54     }
55 }

 

上一篇:继承初体验


下一篇:JavaSE、JavaEE和JavaME有什么区别?