zoukankan      html  css  js  c++  java
  • 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 }
    作者:donleo123
    本文如对您有帮助,还请多推荐下此文,如有错误欢迎指正,相互学习,共同进步。
  • 相关阅读:
    UEditor用法
    String,StringBuffer与StringBuilder差异??
    TsFltMgr.sys其原因是,该系统蓝屏QQ计算机管理器!
    Linux编程实现守护进程
    开机黑屏 只显示鼠标 电脑黑屏 有只老鼠 举 [我们已经成功地解决了]
    页面背景图像的代码
    动态规划01背包问题
    关键部分CCriticalSection使用
    编程:获取股票实时行情数据大全
    iphone开发教程下载
  • 原文地址:https://www.cnblogs.com/donleo123/p/14069872.html
Copyright © 2011-2022 走看看