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将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供更多的子类)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中套接字,如何在java中获得一个开放的套接字?

在Java中,我如何获得一个开放的套接字?我有2个JFrame;在第一个JFrame中,我打开了Client socket的连接.在同一个JFrame中,我创建了另一个JFrame(JFrame2)的实例.现在我想从JFrame1获取相同的Socket到JFrame2继续与我的服务器Socket交谈:login.java(First …

Java多线程(5)--线程通信wait和notify

例题:使用两个线程打印 1-100。线程1, 线程2 交替打印。 解决:涉及wait()和notify()/notifyAll() class Communicate implements Runnable {private int number 1;Overridepublic void run() {while (true) {synchronized (this) {this.notify();if (…

matlab eig 复杂度,MATLAB中的eig函数

在MATLAB中,计算矩阵A的特征值和特征向量的函数是eig(A),常用的调用格式有5种:Eeig(A):求矩阵A的全部特征值,构成向量E。[V,D]eig(A):求矩阵A的全部特征值,构成对角阵D,并求A的特征向…

spring常见面试问题_Spring面试问题

spring常见面试问题另外,请查看我们最新的文章69Spring面试问题与解答–最终清单 。 1)什么是春天? 回答: Spring是控件和面向方面的容器框架的轻量级反转。 2)解释春天? 回答: 轻巧&#x…

Java多线程(6)--Callable接口创建线程

与使用Runnable相比, Callable功能更强大些 ①相比run()方法,可以有返回值 ②方法可以抛出异常 ③支持泛型的返回值 ④需要借助FutureTask类,可以获取返回结果 Future接口 ①可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完…

matlab谱系聚类图,如何看懂SPSS聚类分析的树状图/谱系图?

原创: 数据小兵 SPSS统计训练营SPSS聚类分析提供两种类别图形的输出,第一种是软件默认的“冰柱图”,形状类似于冬天屋檐上垂下的冰柱,因此得名。第二种是“树状图”,在新版本软件中也称谱系图,像一个横着生…

Java多线程(7)--线程池创建线程

经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。 提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中,可以避免频繁创建销毁、实现重复利用。 使用线程池好处&a…

在Google Cloud Platform的K8上运行Fn函数

最近,我在Functions和Project Fn中玩了很多游戏。 最终,我不得不离开笔记本电脑上的操场,进入真正的野生世界。 在K8s集群上运行Fn的想法对我来说很有吸引力,因此我决定在Prem或云中的某个地方进行操作。 在对如何在裸机上自行安装…

php判断对象属于哪个类,PHP instanceof:判断对象是否属于某个类

使用 PHP 中的 instanceof 运算符,可以判断一个对象是否属于某一个类,语法格式如下:对象名 instanceof 类名;【示例】使用 instanceof 判断一个对象是否属于某个类。class A{}class B{}$obj new A;var_dump($obj instanceof A);echo ;var_du…

Java常用类(1)--字符串相关类String、StringBuffer、StringBuilder全面知识

文章目录String类StringBuffer类StringBuilder类String:不可变的字符序列;底层使用char[]存储 StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储 StringBuilder:可变的字符序…

hybbs接口php,HYBBS

#HYBBS官方地址: http://bbs.hyyyp.com论坛基于HYPHP框架开发MVC结构支持HOOK机制PDO操作SQL,支持众多数据库论坛特性服务器环境要求:支持子目录安装论坛PHP 5.3 包括5.3 , 5.3以上环境Apache || Nginx || IIS需要开启伪静态,否则无法安装~!数据库支持 : MYSQL , MSSQL ,Oracle…

Java常用类(2)--日期时间相关类Date、Calendar、LocalDateTime、Instant全面

文章目录java.lang.System类java.util.Date类java.sql.Date类java.text.SimpleDateFormat类java.util.Calendar(日历)类java.time类java.time.Instant类java.time.format.DateTimeFormatter 类其它APIjava.lang.System类 System类提供的public static long currentTimeMillis(…

apache camel_Apache Camel简介

apache camelApache Camel是著名的企业集成模式的开源实现。 Camel是一个路由和中介引擎,可帮助开发人员以各种特定于域的语言(DSL)(例如Java,Spring / XML,scala等)创建路由和中介规则。 骆驼…

oracle括号不区分中英,Oracle的sql语句,查询条件加括号与不加括号区别 -

例如:SELECT ename, job, deptnoFROM empWHERE deptno in (10, 20)AND (ename like ‘%I‘ OR job like ‘%ER‘);执行该sql,结果集如下:1 JONES MANAGER 202 CLARK MANAGER 10去掉上面sql查询条件中的括号&a…

Java常用类(3)--Java比较器Comparable、Comparator类

文章目录自然排序:java.lang.Comparable定制排序:java.util.Comparator自然排序:java.lang.Comparable Comparable接口强行对实现它的每个类的对象进行整体排序,这种排序被称为类的自然排序。 实现 Comparable 的类必须实现 com…

Angular5 JWT身份验证(Spring Boot安全性)

欢迎使用带有Spring Security的angular5 jwt身份验证。在本教程中,我们将在一个angular5单页应用程序中使用jwt身份验证创建一个完整的堆栈应用程序,该应用程序具有由spring boot支持并集成了spring security的后备服务器。带有集成了HttpInterceptor的示…

Java常用类(4)--System类

System类代表系统,系统级的很多属性和控制方法都放置在该类的内部,该类位于java.lang包。 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,可以…

创新设计模式:原型模式

原型模式用于创建对象的副本。 这种模式非常有用,特别是当从头开始创建对象的成本很高时。 与builder , factory和abstract factory模式相比,它不会从头开始创建对象,而是会克隆/重新创建它。 与单例模式相比,它创建一…

oracle游标的实例,oracle游标实例

--游标----游标:当在PL/SQL块中执行查询语句和数据操作语句时,oracle会为其分配上下文区,游标是指向上下文区的指针。----显示游标:显示游标在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开游标,提…

Java常用类(5)--不可变的任意精度BigInteger、BigDecimal类

文章目录BigInteger类BigDecimal类BigInteger类 Integer类作为int的包装类,能存储的最大整型值为2^31-1,Long类也是有限的, 最大为2^63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类 都无能为力。 java.math包的…