JUC学习(一):synchronized的介绍及使用(实现多线程卖票)

简介: JUC学习(一):synchronized的介绍及使用(实现多线程卖票)

一、synchronized简介



synchronized 是 Java 中的关键字,是一种同步锁。它修饰的对象有以下几种:


1、修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{} 括起来的代码,作用的对象是调用这个代码块的对象;

2、修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

3、修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;         4、修改一个类,其作用的范围是 synchronized 后面括号括起来的部分,作用主的对象是这个类的所有对象。


注意:虽然可以使用 synchronized 来定义方法,但 synchronized 并不属于方法定义的一部分,因此,synchronized 关键字不能被继承。如果在父类中的某个方法使用了 synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上synchronized 关键字才可以。当然,还可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。


二、synchronized的简单使用:多人售票案例



本例实现3个人卖30张票

/**
 * synchronized练习,3个人卖30张票
 */
//第一步:创建资源类,定义属性和操作方法
class Ticket{
    //票的数量
    private int number = 30;
    //卖票方法
    public synchronized void sale(){
        if (number > 0){
            System.out.println(Thread.currentThread().getName() + "卖出票,还剩" + --number + "张票");
        }
    }
}
public class SaleTicket {
    //第二步,创建多个线程,调用资源类中的操作方法
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        //线程1
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0; i<40; i++){
                    //卖票
                    ticket.sale();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "售票员A").start();
        //线程2
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    //卖票
                    ticket.sale();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "售票员B").start();
        //线程3
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    //卖票
                    ticket.sale();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "售票员C").start();
    }
}



运行结果:

售票员A卖出票,还剩29张票
售票员B卖出票,还剩28张票
售票员C卖出票,还剩27张票
售票员B卖出票,还剩26张票
售票员C卖出票,还剩25张票
售票员A卖出票,还剩24张票
售票员C卖出票,还剩23张票
售票员B卖出票,还剩22张票
售票员A卖出票,还剩21张票
售票员C卖出票,还剩20张票
售票员B卖出票,还剩19张票
售票员A卖出票,还剩18张票
售票员C卖出票,还剩17张票
售票员B卖出票,还剩16张票
售票员A卖出票,还剩15张票
售票员C卖出票,还剩14张票
售票员B卖出票,还剩13张票
售票员A卖出票,还剩12张票
售票员C卖出票,还剩11张票
售票员B卖出票,还剩10张票
售票员A卖出票,还剩9张票
售票员C卖出票,还剩8张票
售票员B卖出票,还剩7张票
售票员A卖出票,还剩6张票
售票员C卖出票,还剩5张票
售票员A卖出票,还剩4张票
售票员B卖出票,还剩3张票
售票员C卖出票,还剩2张票
售票员B卖出票,还剩1张票
售票员A卖出票,还剩0张票





相关文章
|
1月前
|
缓存 安全 Java
JUC系列之《CountDownLatch:同步多线程的精准发令枪 》
CountDownLatch是Java并发编程中用于线程协调的同步工具,通过计数器实现等待机制。主线程等待多个工作线程完成任务后再继续执行,适用于资源初始化、高并发模拟等场景,具有高效、灵活、线程安全的特点,是JUC包中实用的核心组件之一。
|
30天前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
105 2
|
30天前
|
Java 测试技术 API
【JUC】(1)带你重新认识进程与线程!!让你深层次了解线程运行的睡眠与打断!!
JUC是什么?你可以说它就是研究Java方面的并发过程。本篇是JUC专栏的第一章!带你了解并行与并发、线程与程序、线程的启动与休眠、打断和等待!全是干货!快快快!
300 2
|
30天前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
97 1
|
6月前
|
存储 缓存 安全
JUC并发—11.线程池源码分析
本文主要介绍了线程池的优势和JUC提供的线程池、ThreadPoolExecutor和Excutors创建的线程池、如何设计一个线程池、ThreadPoolExecutor线程池的执行流程、ThreadPoolExecutor的源码分析、如何合理设置线程池参数 + 定制线程池。
JUC并发—11.线程池源码分析
|
10月前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
235 10
|
11月前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
255 7
|
11月前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
405 3
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
149 4
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)

热门文章

最新文章