• 线程同步代码块


    同步代码块

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

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

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

    对于当前同时执行的线程来说 ,同步锁必须是同一把 (同一个对象)否自会出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. }

  • 相关阅读:
    C++超复杂的构造和析构函数执行顺序详解
    【HMS Core】AOSP11安装/预置HMS Core 可以关闭限制广告跟踪吗?
    DT7125C原厂兼容替代多节锂电充电IC管理芯片
    “阿里爸爸”最新Java面试指南,基础+框架+数据库+系统设计+算法
    C#实现二叉排序树定义、插入、构造
    nginx+keepalived集群搭建
    俄罗斯黑客利用Roundcube零日漏洞窃取政府电子邮件
    项目管理逻辑:日志\周报\月报, 一直要求写, 有用吗?
    llinux的更目录下的文件作用和举例
    分布式概念-理论篇
  • 原文地址:https://blog.csdn.net/m0_46290090/article/details/133859116