同步方法及同步代码块

2023-11-06

synchronized方法和synchronized块

synchronized方法必须获得对象的锁才能执行,否则线程阻塞,方法一旦执行,就独占此锁,直到方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行

synchronized会影响效率

同步块synchronized(Obj){},Obj是同步监听器,第一个线程访问,所定Obj,完后解锁Obj,第二个才能访问

同步方法弊端:方法里面需要修改的内容才需要锁,锁的太多,浪费资源

package com.wuming.syn.synch;
//不安全的买票
public class UnSafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();
        new Thread(station,"苦逼的我").start();
        new Thread(station,"牛逼的你们").start();
        new Thread(station,"可恶的黄牛党").start();
    }
}

class BuyTicket implements Runnable{
    //票
    private int ticketNums=10;
    boolean flag=true;//停止方式
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        //买票
        while(flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //synchronized同步方法,锁的是this BuyTicket
    private synchronized void buy() throws InterruptedException {
        //判断是否有票
        if (ticketNums<=0){
            flag=false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        //买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
        //加了synchronized,安全
    /*    苦逼的我拿到10
                可恶的黄牛党拿到9
        可恶的黄牛党拿到8
                牛逼的你们拿到7
        可恶的黄牛党拿到6
                苦逼的我拿到5
        苦逼的我拿到4
                可恶的黄牛党拿到3
        牛逼的你们拿到2
                可恶的黄牛党拿到1*/
    }
}

===============

package com.wuming.syn;
//不安全的取钱
//两个人去银行取钱,账户
public class UnSafeBank {
    public static void main(String[] args) {
        //账户
        Account account = new Account(100,"结婚基金");
        Drawing you = new Drawing(account,50,"你");
        Drawing girlFriend = new Drawing(account,100,"girlFriend");
        you.start();
        girlFriend.start();
    }

}
//账户
class Account{
    int money;//余额
    String name;//卡名

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}

//银行,模拟取款
class Drawing extends Thread{
    Account account;//账户
    //取了多少钱
    int drawingMoney;
    //现在手里有多少钱
    int nowMoney;

    public Drawing(Account account, int drawingMoney, String name) {
        super(name);//线程name
        this.account = account;
        this.drawingMoney = drawingMoney;
        this.nowMoney = nowMoney;
    }
//取钱
    //synchronized默认锁的是本身
    @Override
    public void run() {
        //锁的对象是变化的量,增删改;改成this就是指银行,线程不安全如下
   /*     结婚基金余额为:-50
        结婚基金余额为:-50
        你手里的钱50
                girlFriend手里的钱100*/
        synchronized (account){
            //判断有没有钱
            if(account.money-drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
                return;
            }
            //sleep可以放大问题的发生性
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //卡内余额=余额-你取的钱
            account.money=account.money-drawingMoney;
            //你手里的钱
            nowMoney=nowMoney+drawingMoney;
            System.out.println(account.name+"余额为:"+account.money);
            //Thread.currentThread().getName()=this.getName();
            System.out.println(this.getName()+"手里的钱"+nowMoney);
        }
        //使用同步块 synchronized (account),线程安全
    /*    结婚基金余额为:50
        你手里的钱50
        girlFriend钱不够,取不了*/


    }
}

===============

package com.wuming.syn.synch;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list){//线程安全
                    list.add(Thread.currentThread().getName());
                }
            }).start();
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());//每次运行都不够10000,线程不安全,两个线程同时操作同一个位置,
        //两个数组添加到同一个位置,就会覆盖掉,元素就会少

    }
}

10000

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

同步方法及同步代码块 的相关文章

随机推荐

  • STM8 学习笔记 5:时钟

    1 概述 时钟是单片机的脉搏 是单片机的驱动源 使用任何一个外设都必须打开相应的时钟 这样的好处是 如果不使用一个外设的时候 就把它的时钟关掉 从而可以降低系统的功耗 达到节能 实现低功耗的效果 每个时钟tick 系统都会处理一步数据 这样
  • 图数据库-Neo4j:linux centOS7安装

    1 下载 下载地址 社区版免费 https neo4j com download other releases releases 2 解压 tar axvf neo4j community 3 4 5 unix tar gz 3 修改配置文
  • 完全图解自然语言处理中的Transformer——BERT基础(入门长文)

    翻译自Jay Alammar Blog 在上一篇文章可视化Seq2Seq attention中 我们介绍了现在深度学习中特别常用的Attention 注意力 机制 注意力可以提升机器翻译的效果 这篇文章介绍Transformer 一种使用注
  • 深入理解Netty高性能网络框架

    大家好 今天我们来聊聊Netty的那些事儿 我们都知道Netty是一个高性能异步事件驱动的网络框架 它的设计异常优雅简洁 扩展性高 稳定性强 拥有非常详细完整的用户文档 同时内置了很多非常有用的模块基本上做到了开箱即用 用户只需要编写短短几
  • 平衡二叉树(AVL)python实现

    AVL树是一种特殊的二叉搜索树 BST树 数据极端情况下 二叉搜索树会退化成为单链表 但是AVL树通过旋转操作规避了这个问题 查找平均复杂度 O logn AVL树不适于删除的情况 class AVLTreeNode object def
  • Nginx 配置日志打印--HTTP报文

    http include mime types default type application octet stream log format main remote addr remote user time local request
  • loadrunner12——录制脚本时网络连接错误——无法弹出浏览器解决方法

    loadrunner12可以使用火狐浏览器 如果大家安装有问题 为了避免出错 可根据以下地址重新进行安装 https blog csdn net lmm0513 article details 87935863 1 首先打开loadrunn
  • 1到100, 中间随机抽走一个数,用算法得出是哪个数

    import java util ArrayList import java util HashMap import java util List import java util Map public class HunderTest p
  • UNIX环境高级编程 学习笔记 第二章 UNIX标准及实现

    C语言的ANSI标准在1989年得到批准 此标准也被采纳为国际标准ISO IEC 9899 1990 ANSI是美国国家标准学会 American National Standards Institute 它是国际标准化组织ISO Inte
  • 什么是全国大学生电子设计大赛?如何备战?

    前言 全国大学生电子设计竞赛是教育部和工业和信息化部共同发起的大学生学科竞赛之一 每一届都有非常多的大学生参加 但每届的比赛前夕 总会有很多同学并不清楚比赛的相关信息 流程以及如何去备战比赛 导致在比赛中出现准备不足或违法比赛规则等现象从而
  • C++--封装

    目录 封装 封装的含义 封装的意义1 实例一 实例二 C 面对对象的三大特点 继承 封装 多态 封装 封装的含义 将对象的属性和行为作为一个整体 表现生活中的事物 将属性和行为加以权限控制 封装的意义1 设计一个类 将属性和行为写到一起 表
  • Struts简介

    一 Struts英文单词意思 支柱 支架 来源于建筑和旧式飞机使用的金属支架 二 定义 Struts是流行和成熟的基于MVC设计模式的Web应用程序框架 Struts在软件开发中 是一个非常优秀的框架 它先是Jakarta项目的一个子项目
  • 微服务常见解决方案和高并发常见解决方案、以上特殊解决方案

    我确实比较懒 有些东西总是会写到自己的笔记本上或者在线笔记中 一般很少总结写到博客中 闲来无事确实总结了一些 如果你需要 可以私信聊聊 不敢说有特别好特别完美的方案 但是从个人视角结合知识再结合经验还是有点可说的内容的 如果你需要请私信
  • Parameter ‘name‘ not found. Available parameters are [0, 1, param1, param2]] with root cause

    SpringBoot环境 测试查询数据库 第一次直接通过dao层的注解查询 全局查询没问题 加入参数就报错了 提示说传的参数找不到 打印出来都有值 最后查了一下 这是错误的接口方法 查询注解里的参数有问题 修改为
  • TinyKv流程梳理三

    split流程 处理协程启动 func bs Raftstore startWorkers peers peer ctx bs ctx workers bs workers router bs router bs wg Add 2 raft
  • RecycleView

    鸿洋 Android RecyclerView 使用完全解析 体验艺术般的控件 http blog csdn net lmj623565791 article details 45059587 Android RecycleView 实现滑
  • 虚拟机服务器之间文件拷贝与传输

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 scp scp定义 scp可以实现服务器与服务器之间的数据拷贝 from server1 to server2 二 rsync rsync主要用于备份和镜
  • 开漏输出、推挽输出的区别

    前言 background 测试相关设备引脚输出 使用示波器时发现部分引脚需外接上拉电阻至高电平才能在示波器观察到高阻态 为了深究其中原理 查阅了相关资料 发现知乎中有一篇对这两种输出描述得清晰易懂的文章 此时才真正了解信号高阻态和高电平输
  • SpringBoot--基础--04--拦截器

    SpringBoot 基础 04 拦截器 拦截器 实现HandlerInterceptor接口 注册拦截器 一 代码结构 MyMvcConfig 使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能 Conf
  • 同步方法及同步代码块

    synchronized方法和synchronized块 synchronized方法必须获得对象的锁才能执行 否则线程阻塞 方法一旦执行 就独占此锁 直到方法返回才释放锁 后面被阻塞的线程才能获得这个锁 继续执行 synchronized