摘要:当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。
当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题
模拟线程安全问题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--; } } }死锁问题
同步中嵌套同步,导致锁无法释放
解决办法:尽量避免同步中嵌套同步
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/74525.html
摘要:但是单核我们还是要应用多线程,就是为了防止阻塞。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。 1、多线程有什么用?一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓知其然知其所以然,会用只是知其然,为什么用才是知其所以然,只有达到知其然知其所以然的程度才可以说是把一个知识点...
摘要:是需要我们去处理很多事情,为了防止多线程给我们带来的安全和性能的问题下面就来简单总结一下我们需要哪些知识点来解决多线程遇到的问题。 前言 不小心就鸽了几天没有更新了,这个星期回家咯。在学校的日子要努力一点才行! 只有光头才能变强 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 本文章的知识主要参考《Java并发编程实战》这本书的前4章,这本书的前4章都是讲解并发的基...
摘要:多线程环境下的一些问题安全性问题在没有正确同步的情况下,多线程环境下程序可能得出错误的结果。一些相关概念竞争条件多线程的环境下,程序执行的结果取决于线程交替执行的方式。而线程的交替操作顺序是不可预测的,如此程序执行的结果也是不可预测的。 入口 Java多线程的应用复杂性之如jvm有限的几个内存方面的操作和规范,就像无数纷繁复杂的应用逻辑建立在有限的指令集上。 如何写出线程安全的程序,有...
摘要:的内置锁是一种互斥锁,意味着最多只有一个线程能持有这种锁。使用方式如下使用显示锁之前,解决多线程共享对象访问的机制只有和。后面会陆续的补充并发编程系列的文章。 早期的计算机不包含操作系统,它们从头到尾执行一个程序,这个程序可以访问计算机中的所有资源。在这种情况下,每次都只能运行一个程序,对于昂贵的计算机资源来说是一种严重的浪费。 操作系统出现后,计算机可以运行多个程序,不同的程序在单独...
摘要:程序正常运行,输出了预期容量的大小这是正常运行结果,未发生多线程安全问题,但这是不确定性的,不是每次都会达到正常预期的。另外,像等都有类似多线程安全问题,在多线程并发环境下避免使用这种集合。 这个问题是 Java 程序员面试经常会遇到的吧。 工作一两年的应该都知道 ArrayList 是线程不安全的,要使用线程安全的就使用 Vector,这也是各种 Java 面试宝典里面所提及的,可能...
摘要:下面是线程相关的热门面试题,你可以用它来好好准备面试。线程安全问题都是由全局变量及静态变量引起的。持有自旋锁的线程在之前应该释放自旋锁以便其它线程可以获得自旋锁。 最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案。 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员...
阅读 3002·2021-10-27 14:16
阅读 2842·2021-09-24 10:33
阅读 2226·2021-09-23 11:21
阅读 3202·2021-09-22 15:14
阅读 738·2019-08-30 15:55
阅读 1628·2019-08-30 15:53
阅读 1677·2019-08-29 11:14
阅读 2164·2019-08-28 18:11