Java同步锁(synchronized)、锁(lock)以及死锁

1、实体类

 1 package com.cn.donleo.thread.phone;
 2 
 3 import java.util.concurrent.locks.Lock;
 4 import java.util.concurrent.locks.ReentrantLock;
 5 
 6 /**
 7  * @author liangd
 8  * date 2020-11-02 08:53
 9  * code
10  */
11 public class MyPhone implements Runnable {
12 
13     private int phoneNum = 100;
14     /*
15      * 同步锁的两种方式:
16      * 1、锁对象   synchronized (this)
17      * 2、锁方法   public synchronized void run()   锁方法其实是锁的当前对象,synchronized (this) ,synchronized (MyPhone.class)
18      * 同步锁优缺点:
19      * 1、解决了多线程安全问题
20      * 2、增加了线程同步锁后,必须一个一个执行,浪费资源,降低了程序的运行效率
21      */
22     /**
23      * 1、对不同的runnable传入同一个lock
24      * 2、lock和synchronized类似,只不过这个是手动上锁,手动释放锁
25      *    synchronized属于自动上锁和释放
26      * 3、Lock和synchronized的区别
27      *   1)synchronized试用于并发量小的,lock更适用于并发量大的
28      *   2)lock更灵活,可以自由定义多把锁的枷锁解锁顺序
29      *   3)Lock还有中断锁和定时锁。
30      *   4)当线程运行到synchronized同步方法中,就会拥有obj对象的对象锁
31      *   5)Wait会释放对象锁,sleep不会释放对象锁
32      *   6)Synchronized用对象锁:
33      */
34     private Lock lock = new ReentrantLock();
35 
36     @Override
37     public synchronized void run() {
38         //while(true)是一个无穷循环语句  我们必须在他的循环语句内部加入一个判断  当他达到了什么要求就会跳出
39         while (true) {
40             //锁对象,指当前对象
41 //            synchronized (this){
42 //            synchronized ("Myphone"){
43             if (phoneNum > 0) {
44                 lock.lock();
45                 try {
46                     /*
47                         1、卖手机的时候不可能都是同时卖出或者被预定在MyPhone类里面增加sleep
48                          休眠100毫秒
49                         2、淘宝最后一部手机进来
50                            京东也有人预定手机,现在没有--,也可以进来
51                            同理,拼多多也有人预定手机,现在没有--,也可以进来
52                         3、会出现负数
53                      */
54                     Thread.sleep(100);
55                 } catch (InterruptedException e) {
56                     e.printStackTrace();
57                 } finally {
58                     //lock.unlock()要放在finally里面,因为如果上面报异常的情况下锁就不会手动释放,放在finally里面始终要执行
59                     lock.unlock();
60                 }
61                 System.out.println(Thread.currentThread().getName() + "卖出了一部手机,还剩余" + --phoneNum + "部手机");
62             } else {
63                 System.out.println("手机已经全部卖完,请下次再来");
64                 return;
65             }
66 //            }
67 
68         }
69     }
70 }

 

2、测试同步锁

 1 package com.cn.donleo.thread.phone;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 08:59
 6  * code 线程同步测试
 7  */
 8 public class TestMyPhone {
 9     /**
10      * 手机属于预定模式,分别由京东,淘宝,拼多多三个商家在卖
11      * 现在有华为P40PRO手机100部,怎么来实现
12      * 思考:
13      * 1.有一百部手机
14      * 2.京东,淘宝,拼多多是同时卖手机,属于三个线程
15      * 3.有一个仓库进行发货,这个可以理解为main方法
16      * @param args
17      */
18     public static void main(String[] args){
19         MyPhone myPhone = new MyPhone();
20             Thread tb = new Thread(myPhone,"淘宝");
21             Thread jd = new Thread(myPhone,"京东");
22             Thread pdd = new Thread(myPhone,"拼多多");
23             tb.start();
24             jd.start();
25             pdd.start();
26 
27     }
28 }

 

3、测试死锁

 1 package com.cn.donleo.thread.phone;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 09:42
 6  * code 死锁测试
 7  */
 8 public class TestSynchronized {
 9     /**
10      * 1、死锁4个必要条件
11      *  (1) 互斥条件:一个资源每次只能被一个进程使用。
12      *  (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
13      *  (3) 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
14      *  (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
15      * 2、如何避免死锁
16      *  (1)加锁顺序(线程按照一定的顺序加锁)
17      *  (2)加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
18      *  (3)死锁检测
19      *   最简单的方式:不要写嵌套锁就好
20      */
21     public static void main(String[] args) {
22         /*
23          *  多次测试,出现死锁,程序一直在运行,A和B都没有吃到饭
24          */
25         //匿名内部类,直接new接口必须实现接口中的抽象方法
26         new Thread(new Runnable() {
27             @Override
28             public void run() {
29                 synchronized ("A") {
30                     System.out.println(Thread.currentThread().getName() + "拿到A筷子了");
31                     //嵌套锁
32                     synchronized ("B") {
33                         System.out.println(Thread.currentThread().getName() + "拿到A筷子了,同时拿到B筷子了,可以吃饭了");
34                     }
35                 }
36             }
37         }, "男朋友").start();
38         //再开一个线程
39         new Thread(new Runnable() {
40             @Override
41             public void run() {
42                 synchronized ("B") {
43                     System.out.println(Thread.currentThread().getName() + "拿到B筷子了");
44                     //嵌套锁
45                     synchronized ("A") {
46                         System.out.println(Thread.currentThread().getName() + "拿到B筷子了,同时拿到A筷子了,可以吃饭了");
47                     }
48                 }
49             }
50         }, "女朋友").start();
51     }
52 }

 

posted @ 2020-12-01 18:06  donleo123  阅读(849)  评论(0编辑  收藏  举报