Java多线程(4)--线程的同步解决线程安全问题
多线程出现安全问题
问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
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)--线程的同步解决线程安全问题相关推荐
- 详解Java多线程编程中LockSupport类的线程阻塞用法
转载自 详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...
- Java 多线程详解(五)------线程的声明周期
Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...
- Java性能-线程和同步-JVM线程优化和线程优先级
线程和同步-JVM线程优化 优化线程栈大小 每个线程都有一个原生栈,操作系统会在这里存储线程的调用栈信息,如果空间不足可以通过调整线程使用的内存. 64位机器默认原生栈大小1MB 如果将线程栈设置的非 ...
- JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池...
/*** 多线程共享数据* 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行.* 多线程共享数据的安全问题,使用同步解决.* 线程同步两种方法: ...
- Java 多线程详解(三)------线程的同步
Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...
- 多线程的创建方式和解决线程安全问题
一 基本概念 ①程序(program)是为完成特定任务.用某种语言编写的一组指令的集合.即指一 段静态的代码,静态对象. ②进程(process)是程序的一次执行过程,或是正在运行的一个程序.是一个 ...
- java多线程基础学习[狂神说java-多线程笔记]
java多线程基础学习 一.线程简介 1.类比 2.程序进程线程 3.线程的核心概念 二.线程的实现(重点) 调用方法与调用多线程的区别 Thread 类 1.thread使用方法 2. 代码实现 3 ...
- Java多线程详解(如何创建线程)
嗨喽-小伙伴们我们又见面了, 前面一章,我们了解了线程的基本概念,从这一章,我们开始学习如何创建一个线程.总的说来,在java中,有四种创建线程的方式: 1. 继承Thread类 2. 实现Runna ...
- Java多线程技能(九)——暂停线程
目录 1.suspend与resume方法的使用 2.suspend与resume方法的缺点--独占 3.suspend与resume方法的缺点--不同步 暂停线程意味着此线程还可以恢复运行.在 ...
最新文章
- 使用Lucene.Net实现全文检索
- 安全框架 - Shiro与springMVC整合的注解以及JSP标签
- android socket通信如何抓取,安卓Socket通信实例(客户端、服务端)
- 《SAP高级应用开发》---Idoc学习笔记
- haproxy配置参数详解
- 用python快速合并代码(方便软著申请)
- 信息学奥赛一本通(1083:计算星期几)
- 奔跑吧兄弟变成机器人是哪一期_强竞技的《奔跑吧3》蜕变为“生活服务类综艺”,你还愿意看吗?...
- Spring boot MultipartResolver
- stm32的串口DMA空闲中断接收不等长数据,stm32F1的usart1-DMA-IDLE收发
- DimDate populate data
- 跳槽到新公司,我直接让项目的性能提升了一半。。。
- C# 数组拷贝 byte数组拷贝,char数组拷贝
- 以汉维语音翻译为例-uniapp原生顶部栏维语翻译-使用字体图标
- 驱动人生8新版助力电脑性能起飞
- python 分词及语义识别
- 鸡兔同笼之Python函数
- 微信小程序之数据传递
- js实现图片无缝滚动特效
- 基于粒子群优化算法的最小二乘支持向量机预测模型构建(MATLAB实现)
热门文章
- 适用于MongoDB和Mongometer的SpiderMonkey至V8
- GitHub上Java的Bloom Bloom实现
- Play 2.0框架和XA交易
- 使用迭代器时如何避免ConcurrentModificationException
- Maven的单元测试没有执行的问题
- Linux命令之 umount -- 卸载文件系统
- 浅析 Linux 初始化系统(系统服务管理和控制程序/Init System) -- sysvinit/systemvinit(System V init)
- pytorch实现图像分类代码实例
- java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?
- 多元回归求解 机器学习_金融领域里的机器学习算法介绍:人工神经网络