多线程之同步代码块的使用及工作原理

多线程安全问题

在多线程程序中,安全问题主要是由于CPU在执行程序期间,切换线程而导致的。下面是一段售票案例的代码,代码中存在多线程的安全隐患:

开启三个线程,执行售票操作

class ThreadDemo {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        Thread t0 = new Thread(ticket);
        Thread t1 = new Thread(ticket);
        Thread t2 = new Thread(ticket);
        t0.start();
        t1.start();
        t2.start();
    }
}

Runnable接口实现类实现业务逻辑

class Ticket implements Runnable {
    private int ticket = 100;

    @Override
    public void run() {
        while (true) {
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + "出售了第" + ticket--);
            }
        }
    }
}

上述代码在执行后打印如下结果(由于是多线程程序,可能需要多次程序才会暴露出安全问题)

Thread-0出售了第100
Thread-1出售了第100
Thread-1出售了第99
Thread-1出售了第98
Thread-0出售了第99
Thread-1出售了第97

可以看到,不同的线程出售了同一张票,这就是安全问题

多线程安全问题解决思路

当一个线程在执行数据操作时,无论是否休眠或拥有CPU资源,其他线程只能等待它完成操作才能再次操作,这样就能解决安全问题。
JAVA中提供了一种同步技术,用来解决线程安全问题,公式如下:

 synchronized(任意对象){
    线程要操作的共享数据
 }

套用在上面的例子中,Ticket类代码如下:

class Ticket implements Runnable {

    private int ticket = 100;
    private Object obj = new Object();

    @Override
    public void run() {
        synchronized (obj) {
            while (true) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "出售了第" + ticket--);
                }
            }
        }
    }
}

同步代码块的工作原理

同步代码块关键字synchronized后需要有一个任意对象,这个对象被称为同步锁,又叫对象监视器。当线程执行同步代码时,首先会检查同步锁是否存在,如果存在进入同步代码块执行代码,如果不存在,则无法进入同步代码块。
在上面的例子中,当线程0执行到同步代码块时,线程0就会占有该同步锁,此时同步代码块中就没有同步锁了,如果线程0此时休眠或失去CPU,那么其他的线程会因为没有同步锁而无法进入同步代码块,线程0在执行完毕之后,会将同步锁释放。然后线程开始再次根据CPU的调度运行。这样就保证了数据的安全性和同步性。

总结

同步代码块的工作原理可以总结为两点:

  • 没有同步锁的线程,无法进入同步代码块;
  • 在同步中的线程,执行完同步代码之后,才会释放同步锁;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
同步代码块是指在多线程环境下为了保证共享资源的安全性,对某一段代码加锁,使得同一时刻只有一个线程可以执行这段代码。在定时任务中,同步代码块的作用是确保多个定时任务之间按照设置的时间顺序执行,避免出现并发问题。同步代码块使用可以通过在定时任务的方法上加上@Async注解实现,这样定时任务就会被作为异步任务多线程执行,避免长时间执行的定时任务阻塞其他定时任务的执行。 在引用的代码中可以看到,在同步代码块中,将任务对象加入到队列中,然后通过notify()方法通知等待中的线程,从而开始执行定时任务。同步代码块使用确保了定时任务的安全性和按时执行的顺序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [springboot实现定时任务不同任务异步执行,同一任务同步执行](https://blog.csdn.net/zsj777/article/details/124963464)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [定时任务实现原理详解](https://blog.csdn.net/weixin_44593504/article/details/111467618)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值