您当前的位置: 首页 >  Java

小志的博客

暂无认证

  • 0浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java并发多线程编程——从Java字节码的角度看线程安全性问题

小志的博客 发布时间:2021-04-14 21:49:19 ,浏览量:0

目录
    • 一、单线程获取值案例(没有产生线程安全性问题)
    • 二·、多线程获取值案例(产生线程安全性问题)
    • 三、从字节码角度看线程安全性问题的示例
    • 四、如何解决多线程安全性问题的示例
    • 五、如何产生线程安全性问题

一、单线程获取值案例(没有产生线程安全性问题)

1、代码

package com.xz.thread.t3;

/**
 * @description: 单线程情况下输出没有问题
 * @author: xz
 */
public class Sequeue {
    private int value;

    public int getNext(){
        return value++;
    }

    public static void main(String[] args) {
        Sequeue sequeue = new Sequeue();
        while(true){
            System.out.println(sequeue.getNext());
        }
    }

}

2、输出结果如下: 在这里插入图片描述 3、结论

  • 单线程运行,输出结果依次递增,不会出现重复数据。
二·、多线程获取值案例(产生线程安全性问题)

1、代码

package com.xz.thread.t3;

/**
 * @description: 单线程情况下输出没有问题
 * @author: xz
 */
public class Sequeue {
    private int value;

    public int getNext(){
        return value++;
    }

    public static void main(String[] args) {
        Sequeue sequeue = new Sequeue();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"    "+sequeue.getNext());
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+"    "+sequeue.getNext());
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+"    "+sequeue.getNext());
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

}

2、输出结果如下: 在这里插入图片描述 3、结论

  • 多线程运行,输出结果依次递增,但是会出现重复数据。因此产生安全问题。
三、从字节码角度看线程安全性问题的示例

1、找到第三步编译的Sequeue的字节码文件,如下图: 在这里插入图片描述 2、dos命令行窗口进入t3文件夹,并执行javap -verbose Sequeue.class 命令,如下图: 在这里插入图片描述 3、找到 getNext()方法,如下图: 在这里插入图片描述 4、结论:

  • 由上图可知,getNext方法并不是一步操作即完成,而是分成了多个步骤,所以多线程访问会出现相同数值问题。
四、如何解决多线程安全性问题的示例

1、在getNext方法上加上synchronized关键字,代码如下:

package com.xz.thread.t3;

/**
 * @description: 单线程情况下输出没有问题
 * @author: xz
 */
public class Sequeue {
    private int value;

    public synchronized int getNext(){
        return value++;
    }

    public static void main(String[] args) {
        Sequeue sequeue = new Sequeue();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"    "+sequeue.getNext());
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+"    "+sequeue.getNext());
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+"    "+sequeue.getNext());
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

}

2、输出结果如下图: 在这里插入图片描述

3、结论

  • 由上图输出结果可知,没有重复值的情况,解决了多线程安全性问题。
五、如何产生线程安全性问题
  • 多线程环境下
  • 多个线程共享一个资源
  • 对资源进行非原子性操作
关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.0479s