线程安全问题解决

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vvOqmEjv-1629284758491)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20210818161532498.png)]

方式一(同步代码块)

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

说明:1.操作共享数据的代码,即为需要被同步的代码。 -->不能包含代码多了,也不能包含代码少了。
2.共享数据:多个线程共同操作的变量。比如:ticket就是共享数据。
3.同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
要求:多个线程必须要共用同一把锁。
补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。

package com.atguigu.java;class Window1 implements Runnable{private int ticket = 100;
//    Object obj = new Object();
//    Dog dog = new Dog();@Overridepublic void run() {
//        Object obj = new Object();while(true){synchronized (this){//此时的this:唯一的Window1的对象   //方式二:synchronized (dog) {if (ticket > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);ticket--;} else {break;}}}}
}public class WindowTest1 {public static void main(String[] args) {Window1 w = new Window1();Thread t1 = new Thread(w);Thread t2 = new Thread(w);Thread t3 = new Thread(w);t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}}class Dog{}
package com.atguigu.java;class Window2 extends Thread{private static int ticket = 100;private static Object obj = new Object();@Overridepublic void run() {while(true){//正确的
//            synchronized (obj){synchronized (Window2.class){//Class clazz = Window2.class,Window2.class只会加载一次//错误的方式:this代表着t1,t2,t3三个对象
//              synchronized (this){if(ticket > 0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getName() + ":卖票,票号为:" + ticket);ticket--;}else{break;}}}}
}public class WindowTest2 {public static void main(String[] args) {Window2 t1 = new Window2();Window2 t2 = new Window2();Window2 t3 = new Window2();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

方式二(同步方法)

如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。

关于同步方法的总结:

  1. 同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
  2. 非静态的同步方法,同步监视器是:this
    静态的同步方法,同步监视器是:当前类本身
package com.atguigu.java;class Window3 implements Runnable {private int ticket = 100;@Overridepublic void run() {while (true) {show();}}private synchronized void show(){//同步监视器:this//synchronized (this){if (ticket > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);ticket--;}//}}
}public class WindowTest3 {public static void main(String[] args) {Window3 w = new Window3();Thread t1 = new Thread(w);Thread t2 = new Thread(w);Thread t3 = new Thread(w);t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}}
package com.atguigu.java;/*** 使用同步方法处理继承Thread类的方式中的线程安全问题** @author shkstart* @create 2019-02-15 上午 11:43*/
class Window4 extends Thread {private static int ticket = 100;@Overridepublic void run() {while (true) {show();}}private static synchronized void show(){//同步监视器:Window4.class//private synchronized void show(){ //同步监视器:t1,t2,t3。此种解决方式是错误的if (ticket > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);ticket--;}}
}public class WindowTest4 {public static void main(String[] args) {Window4 t1 = new Window4();Window4 t2 = new Window4();Window4 t3 = new Window4();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

方式三(Lock锁)—JDK5.0新增

1. 面试题:synchronizedLock的异同?相同:二者都可以解决线程安全问题不同:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock()2.优先使用顺序:
Lock 
同步代码块(已经进入了方法体,分配了相应资源) 
同步方法(在方法体之外)
package com.atguigu.java1;import java.util.concurrent.locks.ReentrantLock;/*** 解决线程安全问题的方式三:Lock锁  --- JDK5.0新增** 1. 面试题:synchronized 与 Lock的异同?*   相同:二者都可以解决线程安全问题*   不同:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器*        Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())** 2.优先使用顺序:* Lock  同步代码块(已经进入了方法体,分配了相应资源)  同步方法(在方法体之外)***  面试题:如何解决线程安全问题?有几种方式* @author shkstart* @create 2019-02-15 下午 3:38*/
class Window implements Runnable{private int ticket = 100;//1.实例化ReentrantLockprivate ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while(true){try{//2.调用锁定方法lock()lock.lock();if(ticket > 0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":售票,票号为:" + ticket);ticket--;}else{break;}}finally {//3.调用解锁方法:unlock()lock.unlock();}}}
}public class LockTest {public static void main(String[] args) {Window w = new Window();Thread t1 = new Thread(w);Thread t2 = new Thread(w);Thread t3 = new Thread(w);t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

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

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

相关文章

Chrome DevTools 调研笔记

1 说明 此篇文章针对Chrome DevTools常用功能进行调研分析。描述了每个功能点能实现的功能、应用场景和详细操作。 2 Elements 2.1 功能 检查和实时更新页面的HTML与CSS 在 Elements 面板中检查和实时编辑 DOM 树中的任何元素。在 Styles 窗格中查看和更改应用到任何选…

Ajax响应处理数据的三种格式(主要使用gson包)

Ajax响应处理数据的三种格式 A、普通文本(重点)后台:sevletresp.getWriter().print("Ajax响应成功");前台:jspvar text xhr.responseText;B、JSON格式(重点)1、更改toString方法(了解)Overridepublic String toString…

网站开发人员应该知道的62件事

转载自 网站开发人员应该知道的62件事 有人在Stack Overflow上发问,动手开发网站之前,需要知道哪些事情? 不出意料地,他得到了一大堆回答。 通常情况下,你需要把所有人的发言从头到尾读一遍。但是,Stac…

jzoj1350-游戏(某C组)【SPFA,图,最短路】

前言 每天一道C组题get√ 题目 有一颗树,只有一个树根,Alice有M1块石头,Bob有M2块石头,Alice先移每个人轮流移动石头,谁先把自己的石头全部移动到树根处就失败了,输出游戏胜者。 Input 输入包含多组测试…

java中你知道的这四种代码块吗?

点击上方蓝字关注我们大家好,我是雄雄,今天给大家分享的是:java中的四种代码块什么叫代码块?代码块就是将多行代码封装到一个“{}”中,形成一个独立的代码区,这就构成了代码块,一般常见的代码块…

单例模式懒汉式(线程安全写法)

package com.atguigu.java1;/*** 使用同步机制将单例模式中的懒汉式改写为线程安全的** author shkstart* create 2019-02-15 下午 2:50*/ public class BankTest {}class Bank{private Bank(){}private static Bank instance null;public static Bank getInstance(){//方式一…

DDD理论学习系列(5)-- 统一建模语言

1.引言 上一节讲解了领域模型,领域模型主要是将业务中涉及到的概念以面向对象的思想进行抽象,抽象出实体对象,确定实体所对应的方法和属性,以及实体之间的关系。然后将这些实体和实体之间的关系以某种形式(比如UML、图…

java中你知道这四种代码块吗?

大家好,我是雄雄,今天给大家分享的是:java中构造代码块的用法。 什么叫代码块?代码块将多行代码封装到一个{}中,形成一个独立的代码区,这就够成了代码块,一般常见的代码块是这样的: …

jzoj2152-终极数【堆】

题目(复杂) 给定一个长度为n的序列a,试求出对于序列a的每一个前缀的终极数x,使得 最小,试求出终极数t(如若有多个终极数t,只需输出最小的那个) 正解 其实就是求中位数… 输入 …

谈谈准确率(P值)、召回率(R值)及F值

转载自 谈谈准确率(P值)、召回率(R值)及F值 谈谈准确率(P值)、召回率(R值)及F值 一直总是听说过这几个词,但是很容易记混,在这里记录一下。希望对大家理解…

线程创建两种方式

方式一(继承于Thread类) 创建一个继承于Thread类的子类重写Thread类的run() --> 将此线程执行的操作声明在run()中创建Thread类的子类的对象通过此对象调用start() package com.wdl.java;//1. 创建一个继承于Thread类的子类 class MyThread extends Thread {//2. 重写Thre…

在ASP.NET CORE 2.0使用SignalR技术

一、前言 上次讲SignalR还是在《在ASP.NET Core下使用SignalR技术》文章中提到,ASP.NET Core 1.x.x 版本发布中并没有包含SignalR技术和开发计划中。时间过得很快,MS已经发布了.NET Core 2.0 Preview 2 预览版,距离正式版已经不远了&#xf…

【jzoj】2018/2/2 NOIP普及组——D组模拟赛

前言 今天五道题,难度做起来感觉很难,其实就是纸老虎233。 正题 题目1:公牛数学(jzoj1896) 就是高精乘 输入 第1..2行:每行包含一个十进制数 输出 第1行:输出两个数乘积 样例输入 1111…

java中常见的几种内部类,你会几个?(未完)

点击上方蓝色关注我们!大家好,我是雄雄,今天给大家介绍的是java中的几种内部类。java中常见的几个内部类,你会几个?我会四个!在看每个新知识点时,我们不禁有这样或者那样的疑问,比如…

通俗理解信息熵

转载自 通俗理解信息熵 通俗理解信息熵 前段时间德川和我讲解了决策树的相关知识,里面德川说了一下熵,今天整理了一下,记录下来希望对大家理解有帮助~ 1、信息熵的公式 先抛出信息熵公式如下: 其中代表随机事件X为的概率&…

程序、进程、线程

程序(program) 是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 进程(process) 是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。——生命周期 如…

.NET Core 2.0 Preview 2为开发人员带来改进

Microsoft发布了.NET Core 2第二个预览版(Preview 2),该版本可用于Mac OS X、Linux和Windows平台。Preview 2首次给出了对所有平台上各种软件包和安装程序的统一命名模式。所有的运行时文件将以"dotnet-运行时名称”命名,而S…

java中,剩下的这两个内部类不太好理解!

点击上方蓝色关注我们!大家好,我是雄雄,今天我们接着昨天的分享,将剩余的两个内部类(方法内部类和匿名内部类)结束掉,这两个内部类都不太好理解。昨天的推文:java中常见的几种内部类…

【jzoj】2018.2.3NOIP普及组——D组模拟赛

前言 万年D组系列… 正题 题目1:数池塘(jzoj1898) 有一个地方有一些积水,连着的积水是一个池塘,求池塘数。 输入 第1行:由空格隔开的两个整数:N和M 第2..N1行:每行M个字符代表…

并行与并发

**并行:**多个CPU同时执行多个任务。比如:多个人同时做不同的事。 **并发:**一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事。