多线程出现安全问题

问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。

解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。


Java对于多线程的安全问题提供了专业的解决方式:同步机制


方式一:同步代码块

synchronized(同步监视器){//需要被同步的代码
}

说明:
1.操作共享数据的代码,即为需要被同步的代码。
2.共享数据:多个线程共同操作的变量,比如: 车票就是共享数据。
3.同步监视器,俗称:锁,任何一个类的对象,都可以充当锁。(但是要求:多个线程必须共用同一把锁,即同一个对象)(可以考虑用this充当)(可以考虑类.class充当)

示例:
①Runnable接口实现类

public class MThread implements Runnable{private int ticket = 100;Object obj = new Object();@Overridepublic void run() {while (true) {synchronized (obj) {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + ":票号为" + ticket);ticket--;} else break;}}}
}

②创建并执行多线程

public class TestThread {public static void main(String[] args) {MThread thread = new MThread();Thread curThread1 = new Thread(thread);Thread curThread2 = new Thread(thread);Thread curThread3 = new Thread(thread);curThread1.setName("窗口一");curThread2.setName("窗口二");curThread3.setName("窗口三");curThread1.start();curThread2.start();curThread3.start();}
}

同步的方式,解决了线程的安全问题。
操作同步代码时,只能有一 个线程参与, 其他线程等待,相当于是一个单线程的过程,效率低。

注意:在继承Thread类这种情况下,需要将同步监视器声明为静态的,这样才能保证同一把锁。


方式二:同步方法

synchronized还可以放在方法声明中,表示整个方法为同步方法。

public synchronized void show (){ //其实是有一个同步监视器(锁)this//需要被同步的代码
}

与同步代码块使用类似,只是在run()方法中调用该同步方法。

注意:和使用同步代码块一样,在继承Thread类这种情况下,需要将该同步方法声明为静态的,即public static synchronized void show (),此时的同步监视器相当于是当前类.class

同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
非静态的同步方法,同步监视器是: this
静态的同步方法,同步监视器是:当前类本身


方式三:Lock锁方式

从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步,同步锁使用Lock对象充当。

ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。

class A{private final ReentrantLock lock = new ReenTrantLock();public void run(){lock.lock();try{//保证线程安全的代码;}finally{lock.unlock(); }}
}

synchronized 与 Lock 的对比:

①Lock是显式锁(手动开启和关闭锁),synchronized是隐式锁,出了作用域自动释放。
②Lock只有代码块锁,synchronized有代码块锁和方法锁。
③使用Lock锁,JVM将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供更多的子类)。

Java多线程(4)--线程的同步解决线程安全问题相关推荐

  1. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

  2. Java 多线程详解(五)------线程的声明周期

    Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...

  3. Java性能-线程和同步-JVM线程优化和线程优先级

    线程和同步-JVM线程优化 优化线程栈大小 每个线程都有一个原生栈,操作系统会在这里存储线程的调用栈信息,如果空间不足可以通过调整线程使用的内存. 64位机器默认原生栈大小1MB 如果将线程栈设置的非 ...

  4. JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池...

    /*** 多线程共享数据* 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行.* 多线程共享数据的安全问题,使用同步解决.* 线程同步两种方法: ...

  5. Java 多线程详解(三)------线程的同步

    Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...

  6. 多线程的创建方式和解决线程安全问题

    一  基本概念 ①程序(program)是为完成特定任务.用某种语言编写的一组指令的集合.即指一 段静态的代码,静态对象. ②进程(process)是程序的一次执行过程,或是正在运行的一个程序.是一个 ...

  7. java多线程基础学习[狂神说java-多线程笔记]

    java多线程基础学习 一.线程简介 1.类比 2.程序进程线程 3.线程的核心概念 二.线程的实现(重点) 调用方法与调用多线程的区别 Thread 类 1.thread使用方法 2. 代码实现 3 ...

  8. Java多线程详解(如何创建线程)

    嗨喽-小伙伴们我们又见面了, 前面一章,我们了解了线程的基本概念,从这一章,我们开始学习如何创建一个线程.总的说来,在java中,有四种创建线程的方式: 1. 继承Thread类 2. 实现Runna ...

  9. Java多线程技能(九)——暂停线程

    目录 1.suspend与resume方法的使用 2.suspend与resume方法的缺点--独占 3.suspend与resume方法的缺点--不同步   暂停线程意味着此线程还可以恢复运行.在 ...

最新文章

  1. 使用Lucene.Net实现全文检索
  2. 安全框架 - Shiro与springMVC整合的注解以及JSP标签
  3. android socket通信如何抓取,安卓Socket通信实例(客户端、服务端)
  4. 《SAP高级应用开发》---Idoc学习笔记
  5. haproxy配置参数详解
  6. 用python快速合并代码(方便软著申请)
  7. 信息学奥赛一本通(1083:计算星期几)
  8. 奔跑吧兄弟变成机器人是哪一期_强竞技的《奔跑吧3》蜕变为“生活服务类综艺”,你还愿意看吗?...
  9. Spring boot MultipartResolver
  10. stm32的串口DMA空闲中断接收不等长数据,stm32F1的usart1-DMA-IDLE收发
  11. DimDate populate data
  12. 跳槽到新公司,我直接让项目的性能提升了一半。。。
  13. C# 数组拷贝 byte数组拷贝,char数组拷贝
  14. 以汉维语音翻译为例-uniapp原生顶部栏维语翻译-使用字体图标
  15. 驱动人生8新版助力电脑性能起飞
  16. python 分词及语义识别
  17. 鸡兔同笼之Python函数
  18. 微信小程序之数据传递
  19. js实现图片无缝滚动特效
  20. 基于粒子群优化算法的最小二乘支持向量机预测模型构建(MATLAB实现)

热门文章

  1. 适用于MongoDB和Mongometer的SpiderMonkey至V8
  2. GitHub上Java的Bloom Bloom实现
  3. Play 2.0框架和XA交易
  4. 使用迭代器时如何避免ConcurrentModificationException
  5. Maven的单元测试没有执行的问题
  6. Linux命令之 umount -- 卸载文件系统
  7. 浅析 Linux 初始化系统(系统服务管理和控制程序/Init System) -- sysvinit/systemvinit(System V init)
  8. pytorch实现图像分类代码实例
  9. java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?
  10. 多元回归求解 机器学习_金融领域里的机器学习算法介绍:人工神经网络