zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java学习-077-多线程10:线程资源同步问题实例演示

2023-09-11 14:18:59 时间

如果通过 Runnable 接口实现多线程,则多线程实现类中的属性可被多个线程共享。当多个线程同时操作线程同一个共享资源时,有大概率出现资源同步问题,导致最终的结果偏离我们预期的最终结果,甚至完全相反。

下面通过一个简单实例,演示一下多线程的资源同步问题,示例源代码如下所示:

package com.fanfengping.demo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Demo14RunnableSync implements Runnable {
    private int stockTicket = 50;
    private int saleTicket = 0;

    @Override
    public void run() {
        while (stockTicket > 0) {
            log.info("{} 出票一张,售出票数:{},剩余票数:{}", Thread.currentThread().getName(), ++saleTicket, --stockTicket);
        }
    }

    public static void main(String[] args) {
        Demo14RunnableSync demo14RunnableSync = new Demo14RunnableSync();

        for (int i = 1; i < 5; i++) {
            new Thread(demo14RunnableSync, "窗口" + i).start();
        }
    }
}

  

执行程序,输出的结果如下所示:

[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:3,剩余票数:47
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:1,剩余票数:49
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:5,剩余票数:45
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:6,剩余票数:44
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:7,剩余票数:43
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:8,剩余票数:42
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:9,剩余票数:41
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:4,剩余票数:46
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:10,剩余票数:40
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:2,剩余票数:48
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:11,剩余票数:39
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:12,剩余票数:38
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:14,剩余票数:36
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:16,剩余票数:34
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:13,剩余票数:37
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:17,剩余票数:33
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:18,剩余票数:32
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:19,剩余票数:31
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:15,剩余票数:35
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:21,剩余票数:29
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:20,剩余票数:30
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:23,剩余票数:27
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:24,剩余票数:26
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:22,剩余票数:28
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:25,剩余票数:25
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:26,剩余票数:24
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:27,剩余票数:23
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:29,剩余票数:21
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:30,剩余票数:20
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:25,剩余票数:25
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:28,剩余票数:22
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:31,剩余票数:19
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:34,剩余票数:16
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:32,剩余票数:18
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:35,剩余票数:15
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:36,剩余票数:14
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:37,剩余票数:13
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:39,剩余票数:11
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:33,剩余票数:17
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:40,剩余票数:10
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:38,剩余票数:12
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:41,剩余票数:9
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:42,剩余票数:8
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:43,剩余票数:7
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:44,剩余票数:6
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:45,剩余票数:5
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:46,剩余票数:4
[窗口2] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口2 出票一张,售出票数:48,剩余票数:2
[窗口1] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口1 出票一张,售出票数:47,剩余票数:3
[窗口3] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口3 出票一张,售出票数:50,剩余票数:0
[窗口4] INFO com.fanfengping.demo.Demo14RunnableSync - 窗口4 出票一张,售出票数:49,剩余票数:1

  

由此可见,多线程操作无保护同一线程资源时,会导致预期偏离。

那么,如何解决多线程资源同步问题呢? Java 中可通过同步代码块(synchronized)实现,具体示例请参阅后续文章。