首页 > 编程语言 >java多线程 读取变量同步安全的案例

java多线程 读取变量同步安全的案例

时间:2024-04-17 15:37:20浏览次数:30  
标签:java 读取 synchronized getName System ticket 多线程 public out

本次介绍,我使用的是synchronized 同步代码块的关键字来读取list,在写java多线程时,一定要注意

synchronized 关键字的有效范围。
ps:
如果synchronized 关键字的代码块范围太大,可能会导致 优先获取到cpu资源的第一个线程 在满足条件的情况下 一直无法跳循环,从而使得其他线程
无法给获取到被cpu调度的机会,造成:想“多线程执行代码块”的预期-》演变成了 “单线程一路走到黑 执行代码块”的惨象,也就是让多线程的预期 实际变成了单线程了。
以下 我就用1个错误的例子,和一个正确的例子给大家介绍以下吧:
1.错误的例子:实际是单线程 执行synchronized代码块的内容:
package com.cdncp.testautomation.control.schedule;

public class SellTicketTest {
    public static void main(String[] args) {
        for(int i=0;i<9;i++){
            TicketSell t1 = new TicketSell();
            t1.setName("第"+i+"号窗口");
            t1.start();
        }
//        TicketSell t1 = new TicketSell();
//        TicketSell t2 = new TicketSell();
//        TicketSell t3 = new TicketSell();
//        TicketSell t4 = new TicketSell();
//
//        t1.setName("第一号窗口");
//        t2.setName("第二号窗口");
//        t3.setName("第三号窗口");
//        t4.setName("第四号窗口");
//
//        t1.start();
//        t2.start();
//        t3.start();
//        t4.start();
    }
}

第二个类:

package com.cdncp.testautomation.control.schedule;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TicketSell extends Thread {
    private static int ticket = 20;
    private static final Lock lock = new ReentrantLock();

    @Override
    public void run() {
//        System.out.println(this.getName() + "卖出第 " + ticket + "号票");
        System.out.println(this.getName() + "卖出第 " + ticket + "号票");
        while (true) {
            synchronized (TicketSell.class) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
//                synchronized (TicketSell.class) {
                    if (ticket > 0) {
                        ticket--;
                        System.out.println(this.getName() + "---------------------卖出第 " + ticket + "号票");
                    }

//                }
                } else {
                    System.out.printf("%s:票已售空 \n", Thread.currentThread().getName());
                    break;
                }
            }
        }
    }


}

执行结果:

 

2.正确的例子:实现多线程 执行synchronized代码块的内容:
package com.cdncp.testautomation.control.schedule;

public class SellTicketTest {
    public static void main(String[] args) {
// 方法一:创建9个线程
        for(int i=0;i<9;i++){
            TicketSell t1 = new TicketSell();
            t1.setName("第"+i+"号窗口");
            t1.start();
        }
// 方法二:创建9个线程
//        TicketSell t1 = new TicketSell();
//        TicketSell t2 = new TicketSell();
//        TicketSell t3 = new TicketSell();
//        TicketSell t4 = new TicketSell();
//
//        t1.setName("第一号窗口");
//        t2.setName("第二号窗口");
//        t3.setName("第三号窗口");
//        t4.setName("第四号窗口");
//
//        t1.start();
//        t2.start();
//        t3.start();
//        t4.start();
    }
}
package com.cdncp.testautomation.control.schedule;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TicketSell extends Thread {
    private static int ticket = 20;
    private static final Lock lock = new ReentrantLock();

    @Override
    public void run() {
//        System.out.println(this.getName() + "卖出第 " + ticket + "号票");
        System.out.println(this.getName() + "卖出第 " + ticket + "号票");
        while (true) {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (TicketSell.class) {
                    if (ticket > 0) {
                        ticket--;
                        System.out.println(this.getName() + "---------------------卖出第 " + ticket + "号票");
                    }

                }
            } else {
                System.out.printf("%s:票已售空 \n", Thread.currentThread().getName());
                break;
            }
        }
    }

}

 

执行结果:

 

标签:java,读取,synchronized,getName,System,ticket,多线程,public,out
From: https://www.cnblogs.com/pingguomang/p/18140845

相关文章

  • Java登陆第四十三天——Pinia
    到目前一共学习了两种传参方式。 1.组件传参 2.路由传参这两种传参方式并不好用,所以出现了PiniaPinia平替了Vuex,而且比它更优秀。Pinia是Vue衍生的生态系统之一,所以,在使用它前需要导入依赖。npmipinia简单地说,Pinia就是共享数据。各个.vue组件可以利用Pinia更好的完成......
  • KMP算法 Java实现
    Problem:28.找出字符串中第一个匹配项的下标目录解题方法思路构建next数组回溯查找复杂度Code解题方法构建next串回溯查找next串,最后下标思路通过最大前缀后缀能找到下一次未查找到后要回溯的位置构建next数组无论如何第一个数的下一次回溯位置肯定是0,因此next[......
  • 2.JAVA入门 了解JAVA 配置环境
    Java入门Java特性和优势简单性:Java语言设计简洁,易于学习和使用。它摒弃了许多复杂的特性和语法,使得编程变得更加直观和容易上手。面向对象:Java是一种纯粹的面向对象编程语言,所有的代码都以类和对象的形式组织。这种面向对象的特性使得代码更加模块化、可重用性更高,并且更容易......
  • day14_我的Java学习笔记 (常用API、Lambda、常见算法)
    1.常用API1.1Date类【案例】:计算出当前时间往后走1小时121秒之后的时间是多少。1.2SimpleDateFormat【练习】:秒杀活动1.3Calendar2.JDK8新增日期类2.1概述、LocalTime/LocalDate/LocalDateTime2.2Ins......
  • IDEA2023版本创建Spring项目只能勾选17和21却无法使用Java8的完美解决方案
    参考:https://www.jb51.net/program/308256k4b.htm方案一:替换创建项目的源我们只知道IDEA页面创建Spring项目,其实是访问springinitializr去创建项目。故我们可以通过阿里云国服去间接创建Spring项目。将https://start.spring.io/或者http://start.springboot.io/替换为https://......
  • day12_我的Java学习笔记 (package包、权限修饰符_private+缺省+protected+public、fin
    1.包IDEA配置自动导包:2.权限修饰符同一个类中的,【private、缺省、protected、public】都可以访问同一个包中的其他类,【private】不可以访问,【缺省、protected、public】都可以访问不同包下的无关类,【private、缺省、protected】都不可以访问,只有【public......
  • 2.JavaScript
    变量/对象声明var-绑定到window,无法清理,且重复声明会污染全局(尽量不用)let-只在let命令所在的代码块{}内有效const-与let类似但它是只读常量,值不可修改参考视频增删改查letobj={}//创建对象obj.a=1//新增属性a,值为1obj['1']=1//新增属性1,值为1(可以在属性为数......
  • 控制台连接数据库成功,驱动也导入了没问题,但tomcat的servlet启动会报错。报错信息:java.
    查了很多资料这个报错信息是因为驱动导入不成功,但我确定我已经导入了,因为我在控制台输出了出来。找了很久,发现了这个小问题。原因是我在Eclipse中创建是一个标准的Web工程,它是自带lib文件夹的,然后我自己又自建了一个lib文件夹用来放驱动,结果就像这样报出一个错误!解决方案:......
  • 01 多线程
    线程,进程,多线程继承Thread类//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程线程开始不一定立即执行,由CPU调度执行packagecom.mysoft.demo01;//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程//总结:注意,线程开始不一定立即执行,由CPU调度执行pub......
  • java基础模块一
    1java基础(来自B站尚硅谷)1.1字符编码问题1,编码:保存数据的过程2.解码:读数据的过程3.注意:a.编码解码遵守的编码规范必须一致b.常见的两个编码规范: GBK:专门为仲文设计的编码ANSI代表的是GBK一个中文汉字在GBK中占2个字节 UTF-8:一个中文......