java多线程 线程安全问题

栏目: Java · 发布时间: 6年前

内容简介:当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题结果:火车票会重复出售使用多线程之间同步synchronized或使用锁(lock)

当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题

模拟线程安全问题

public class SafeThread implements Runnable {

    private int ticketCount = 50;

    @Override
    public void run() {
        while (ticketCount > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
            ticketCount--;
        }
    }
}
@RequestMapping("test-safe")
    public void testSafe() {
        SafeThread safeThread = new SafeThread();
        Thread t1 = new Thread(safeThread, "thread-1");
        Thread t2 = new Thread(safeThread, "thread-2");
        t1.start();
        t2.start();
    }

结果:火车票会重复出售

解决办法

使用多线程之间同步synchronized或使用锁(lock)

1.同步代码块

public class SafeThread implements Runnable {

    private int ticketCount = 50;

    @Override
    public void run() {
        while (ticketCount > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
                ticketCount--;
            }
        }
    }
}

2.同步方法

public class SafeThread implements Runnable {

    private int ticketCount = 50;

    @Override
    public void run() {
        while (ticketCount > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            synchronized (this) {
//                System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
//                ticketCount--;
//            }
            sale();
        }
    }

    private synchronized void sale() {
        System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
        ticketCount--;
    }
}

注意:同步函数使用this锁

3.静态同步函数

方法上加上static关键字,使用synchronized 关键字修饰或者使用类.class文件。

静态的同步函数使用的锁是该函数所属字节码文件对象

可以用 getClass方法获取,也可以用当前类名.class 表示

public class SafeThread implements Runnable {

    private int ticketCount = 50;

    @Override
    public void run() {
        while (ticketCount > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            synchronized (this) {
//                System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
//                ticketCount--;
//            }
//            sale();
            sale2();
        }
    }

    private synchronized void sale() {
        System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
        ticketCount--;
    }


    private void sale2() {
        synchronized (SafeThread.class) {
            System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
            ticketCount--;
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

爆发

爆发

[美] 艾伯特-拉斯洛·巴拉巴西 / 马慧 / 中国人民大学出版社 / 2012-6 / 59.90元

1. 本书是一本超越《黑天鹅》的惊世之作。如果说塔勒布认为人类行为是随机的,都是小概率事件,是不可以预测的;那么全球复杂网络权威Barabasi则认为,人类行为93%是可以预测的。 2. Barabasi的研究是在人类生活数字化的大数据时代基础上进行的,移动电话、网络以及电子邮件使人类 行为变得更加容易量化,将我们的社会变成了一个巨大的数据库。他认为,人类正处在一个聚合点上,在这里数据、科学......一起来看看 《爆发》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具