• 线程同步代码块


    同步代码块

    作用:把访问共享资源的核心代码给上锁  ,以此保证线程安全

    原理:每次只有允许一个线程加锁以后进入。执行完毕以后自动解锁 。     

       其他线才可以进来执行。同步代码的注意事项

    对于当前同时执行的线程来说 ,同步锁必须是同一把 (同一个对象)否自会出bug

    同步代码块上锁的方法

    1、是同步代码块好还是同步方法好一点?
    范围上:同步代码块锁的范围更小,同步方法锁的范围更大

    同步代码块的性能好因为范围小 

    还有一种直接写到修饰符后面

    注意
    Lock锁是IDK5开始提供的一个新的锁定操作,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便、更强大

    Lock是接口,不能直接实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象。

    创建Lock对象  

    调用Iock对象 加锁

    解锁如果出现bug程序卡在质量

    1. package SafetyTest;
    2. import java.time.LocalDateTime;
    3. import java.util.concurrent.locks.Lock;
    4. import java.util.concurrent.locks.ReentrantLock;
    5. public class Account {
    6. private String carId; //卡号
    7. private double money ;//余额
    8. private final Lock lk= new ReentrantLock();
    9. public Account() {
    10. }
    11. public Account(String carId, double money) {
    12. this.carId = carId;
    13. this.money = money;
    14. }
    15. public void drawMoney(double mony) {
    16. lk.lock();
    17. //先知道那个人来取钱
    18. String name= Thread.currentThread().getName();
    19. if (this.money>=mony){
    20. System.out.println(name+"来取钱"+mony+"成功!");
    21. this.money-=mony;
    22. System.out.println(name+"来取钱后:剩余的“:"+this.money);
    23. }else{
    24. System.out.println(name+"来取钱:余额不足~~!");
    25. }
    26. lk.unlock();
    27. }
    28. public String getCarId() {
    29. return carId;
    30. }
    31. public void setCarId(String carId) {
    32. this.carId = carId;
    33. }
    34. public double getMoney() {
    35. return money;
    36. }
    37. public void setMoney(double money) {
    38. this.money = money;
    39. }
    40. }

    1. package SafetyTest;
    2. public class DrawThread extends Thread {
    3. private Account acc;
    4. public DrawThread(Account acc, String name){
    5. super(name);
    6. this.acc=acc;
    7. }
    8. @Override
    9. public void run() {
    10. super.run();
    11. //取钱
    12. acc.drawMoney(10000);
    13. }
    14. }
    1. package SafetyTest;
    2. public class ThreadSafety {
    3. //模拟线程安全问题
    4. public static void main(String[] args) {
    5. //1:创建一个账户对象 代表两个人的共享账户
    6. Account acc=new Account("ICBC",10000);
    7. //创建两个线程 分别两个人 再去同一个账户里取钱10000
    8. Account acc1=new Account("ICBC",10000);
    9. new DrawThread(acc1,"第一个人1").start(); //第1个人
    10. new DrawThread(acc1,"第二个人2") .start(); //第2个人
    11. new DrawThread(acc,"第一个人").start(); //第1个人
    12. new DrawThread(acc,"第二个人").start(); //第2个人
    13. }
    14. }

  • 相关阅读:
    java毕业生设计校园绿化管理系统计算机源码+系统+mysql+调试部署+lw
    配置基于接口的ARP表项限制和端口安全(限制用户私自接入傻瓜交换机或非法主机接入)
    Kubernetes - Ingress暴露应用(四)
    复现一个循环以及俩个循环问题
    Js基础——事件流
    Strings数据类型
    远程IO模块物联网应用提高工业自动化生产效率
    JS手机号码正则
    澳洲猫罐头到底怎么样呢?我自己亲自喂养过的优质猫罐头分享
    Metabase的基本使用:10分钟快速入门
  • 原文地址:https://blog.csdn.net/m0_46290090/article/details/133859116