文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java线程安全状态的示例分析

2023-06-29 08:55

关注

这篇文章主要为大家展示了“Java线程安全状态的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java线程安全状态的示例分析”这篇文章吧。

一、观察线程的所有状态

线程的状态是一个枚举类型 Thread.State

 public static void main(String[] args) {        for (Thread.State state : Thread.State.values()){            System.out.println(state);        }    }

NEW: 安排了工作, 还未开始行动

RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作.就绪状态

BLOCKED: 这几个都表示排队等着其他事情

WAITING: 这几个都表示排队等着其他事情

TIMED_WAITING: 这几个都表示排队等着其他事情

TERMINATED: 工作完成了.

二、线程状态和状态转移的意义

Java线程安全状态的示例分析

NEW:Thread对象有了,但是PCB还没有

RUNNABLE:线程正在CPU上执行或者即将到CPU上执行(PCB在就绪队列中,随时可能被调度到)

WAITING:wait方法导致

TIMED_WAITING:sleep方法导致

BLOCKED:等待锁导致

TERMINATED:对象还在,但PCB已经没了

public static void main(String[] args) {        Thread t = new Thread(){            @Override            public void run() {                for (int i = 0; i < 100_00; i++){                 }            }        };        System.out.println("线程启动前:" + t.getState());         t.start();        while (t.isAlive()){            System.out.println("线程运行中:" + t.getState());        }        System.out.println("线程结束后:" + t.getState());    }

Java线程安全状态的示例分析

三、多线程带来的风险

线程不安全的原因

①线程是抢占式执行的

线程不安全的万恶之源,线程之间的调度完全由内核负责,用户代码中感知不到,也无法控制。线程之间谁先执行,谁后执行,谁执行到哪里从CPU上下来,这样的过程用户无法控制也无法感知到的。

②自增操作不是原子的

每次++都能拆成三个步骤

        把内存中的数据读取到CPU中

        把CPU中的数据+1

        把计算的数据写回内存中

Java线程安全状态的示例分析

如果两个线程串行执行,此时计算结果为2。

如果两个线程并行执行,线程1进行++操作到一半的时候,线程也进行了++操作,此时自增两次,但结果为1。

必须保证线程1save结束了,线程2再load,此时计算结果才正确

③多个线程尝试修改同一个变量

如果是一个线程修改一个变量,线程安全

如果多个线程读取同一个变量,线程安全

如果多个线程修改不同的变量。线程安全

④内存可见性导致线程安全问题

⑤指令重排序

Java的编译器在编译代码时,会对指令进行优化,调整指令的先后顺序,保证原有的逻辑不变的情况下,提高程序的运行效率

四,解决线程安全问题

锁-synchronized

未加锁

static class Counter{        public int count = 0;          public void increase(){            count++;        }    }     public static void main(String[] args) throws InterruptedException {        Counter counter = new Counter();        Thread t1 = new Thread(){            @Override            public void run() {                for (int i = 0; i < 50000; i++){                    counter.increase();                }            }        };        Thread t2 = new Thread(){            @Override            public void run() {                for (int i = 0; i < 50000; i++){                    counter.increase();                }            }        };        t1.start();        t2.start();        t1.join();        t2.join();         System.out.println(counter.count);    }

Java线程安全状态的示例分析

Java线程安全状态的示例分析

Java线程安全状态的示例分析

 已加锁

static class Counter{        public int count = 0;         synchronized public void increase(){            count++;        }    }     public static void main(String[] args) throws InterruptedException {        Counter counter = new Counter();        Thread t1 = new Thread(){            @Override            public void run() {                for (int i = 0; i < 50000; i++){                    counter.increase();                }            }        };        Thread t2 = new Thread(){            @Override            public void run() {                for (int i = 0; i < 50000; i++){                    counter.increase();                }            }        };        t1.start();        t2.start();        t1.join();        t2.join();         System.out.println(counter.count);    }

Java线程安全状态的示例分析

Java线程安全状态的示例分析

此处的synchronized就是针对counter这个对象来加锁,进入increase方法内部,就把加锁状态设为ture,increase方法退出之后,就把加锁状态设为false,如果某个线程已经把加锁状态设为ture,此处的其他的线程尝试去加锁,就会阻塞

synchronized的特性——刷新内存

synchronized 的工作过程:

        1. 获得互斥锁

        2. 从主内存拷贝变量的最新副本到工作的内存

        3. 执行代码

        4. 将更改后的共享变量的值刷新到主内存

        5. 释放互斥锁

synchronized的特性——互斥

 public static void main(String[] args) {        Object locker = new Object();         Thread t1 = new Thread(){            @Override            public void run() {                Scanner scanner = new Scanner(System.in);                synchronized (locker) {                    System.out.println("输入一个整数");                    int num = scanner.nextInt();                    System.out.println("num= " + num);                }            }        };        t1.start();         Thread t2 = new Thread(){            @Override            public void run() {                while (true){                    synchronized (locker){                        System.out.println("线程2获取到锁");                        try {                            Thread.sleep(1000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                }            }        };        t2.start();    }

Java线程安全状态的示例分析

一旦线程一获取到锁,并且没有释放的话,线程2就会一直在锁这里阻塞等待

 public static void main(String[] args) {        Object locker1 = new Object();        Object locker2 = new Object();         Thread t1 = new Thread(){            @Override            public void run() {                Scanner scanner = new Scanner(System.in);                synchronized (locker1) {                    System.out.println("输入一个整数");                    int num = scanner.nextInt();                    System.out.println("num= " + num);                }            }        };        t1.start();         Thread t2 = new Thread(){            @Override            public void run() {                while (true){                    synchronized (locker2){                        System.out.println("线程2获取到锁");                        try {                            Thread.sleep(1000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                }            }        };        t2.start();    }

Java线程安全状态的示例分析

 不是同一把锁,就不回出现竞争,就没有互斥了。

public static void main(String[] args) {        Object locker1 = new Object();        Object locker2 = new Object();         Thread t1 = new Thread(){            @Override            public void run() {                Scanner scanner = new Scanner(System.in);                synchronized (locker1.getClass()) {                    System.out.println("输入一个整数");                    int num = scanner.nextInt();                    System.out.println("num= " + num);                }            }        };        t1.start();         Thread t2 = new Thread(){            @Override            public void run() {                while (true){                    synchronized (locker2.getClass()){                        System.out.println("线程2获取到锁");                        try {                            Thread.sleep(1000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                }            }        };        t2.start();    }

Java线程安全状态的示例分析

这个代码中,两个线程都在针对locker1和locker2的类对象进行竞争,此处的locker1和locker2的类型都是Object,对应的对象都是相同的对象。 

以上是“Java线程安全状态的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯