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
    本文如对您有帮助,还请多推荐下此文,如有错误欢迎指正,相互学习,共同进步。
  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/donleo123/p/14069872.html
Copyright © 2011-2022 走看看