卖票的过程中出现了线程安全问题,有重票和错票的问题。为什么会出现这个问题?当某个线程在操作卖票的过程中尚未完成卖票操作,其他线程也参与进来操作卖票,就会出现线程安全问题,(主要是共享数据(nums)的问题)怎么去解决这个问题?当某个线程在操作卖票的时候,其他线程不能参与进来,直到这个线程操作完成(即使这个线程阻塞了也得等这个线程执行完成),其他线程才能进来。java里面我们通过同步机制来解决线程安全问题方式一:同步代码块synchronized(同步监视器){}说明:(1)操作共享数据的代码即为需要被同步的代码,不能包含的代码太多会浪费资源,降低效率。(2)共享数据:多个线程共同操作的变量。比如卖票里面的nums(3)同步监视器俗称锁,任何一个类的对象都可以充当锁,但是前提是这个对象对于多个线程来说都是唯一的。
补充:在实现Runnable接口创建线程对象的方式中,我们可以考虑使用this充当同步监视器,如果是使用继承Thread类的方式新建的线程对象则慎用This(可能会有多个对象),可以使用类.class来当同步监视器。
package com.jinjian;/**卖票的过程中出现了线程安全问题,有重票和错票的问题。为什么会出现这个问题?当某个线程在操作卖票的过程中尚未完成卖票操作,其他线程也参与进来操作卖票,就会出现线程安全问题,(主要是共享数据(nums)的问题)怎么去解决这个问题?当某个线程在操作卖票的时候,其他线程不能参与进来,直到这个线程操作完成(即使这个线程阻塞了也得等这个线程执行完成),其他线程才能进来。java里面我们通过同步机制来解决线程安全问题方式一:同步代码块synchronized(同步监视器){}说明:(1)操作共享数据的代码即为需要被同步的代码,不能包含的代码太多会浪费资源,降低效率。(2)共享数据:多个线程共同操作的变量。比如卖票里面的nums(3)同步监视器俗称锁,任何一个类的对象都可以充当锁,但是前提是这个对象对于多个线程来说都是唯一的。
补充:在实现Runnable接口创建线程对象的方式中,我们可以考虑使用this充当同步监视器,如果是使用继承Thread类的方式新建的线程对象则慎用This(可能会有多个对象),可以使用类.class来当同步监视器。方式二:同步方法*/
class Window implements Runnable{private int nums = 100;Object object = new Object();@Overridepublic void run() {while (true) {
//            synchronized (object) {synchronized (this) {if (nums > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为: " + nums);nums--;} else {break;}}}}
}class Window1 extends Thread{private static int nums = 100;@Overridepublic void run() {while (true) {synchronized (Window1.class) {if (nums > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为: " + nums);nums--;} else {break;}}}}
}
public class ThreadTest03 {public static void main(String[] args) {//这样相当于新建了三个Window1对象,要想共享nums变量就需要用static修饰nums。//而且不能用this作为对象监视器,三个对象有三个this不能保证对象监视器的唯一//可以使用Window1.class来作为对象监视器Window1 w1 = new Window1();Window1 w2 = new Window1();Window1 w3 = new Window1();w1.start();w2.start();w3.start();//使用实现Runnable接口来新建线程对象
//        Window window = new Window();//这样nums就是共用的变量,不需要加static,因为只创建了一个Window对象,下面三个线程对象共用一个Window对象//        Thread t1 = new Thread(window);
//        Thread t2 = new Thread(window);
//        Thread t3 = new Thread(window);
//
//        t1.start();
//        t2.start();
//        t3.start();}
}
使用同步方法来解决线程安全问题,(1)同步方法依然涉及到同步监视器,只是不需要我们说明(2)非静态的同步方法的监视器默认是this,静态方法的同步监视器是当前类本身
package com.jinjian;/**
使用同步方法来解决线程安全问题,(1)同步方法依然涉及到同步监视器,只是不需要我们说明(2)非静态的同步方法的监视器默认是this,静态方法的同步监视器是当前类本身*/class Window2 implements Runnable{private int nums = 100;@Overridepublic void run() {while (true) {seal();}}private synchronized void seal(){//这样默认的同步监视器是thisif (nums > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为: " + nums);nums--;}}
}class Window3 extends Thread{private static int nums = 100;@Overridepublic void run() {while (true) {
//            synchronized (Window1.class) {seal();//}}}//    private synchronized void seal(){//这样是不行的,This不唯一有三个对象private static synchronized void seal(){//这样默认的同步监视器是Window3.classif (nums > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为: " + nums);nums--;}}
}public class ThreadTest04 {public static void main(String[] args) {//        Window2 window2 = new Window2();
//
//        Thread t1 = new Thread(window2);
//        Thread t2 = new Thread(window2);
//        Thread t3 = new Thread(window2);
//
//        t1.start();
//        t2.start();
//        t3.start();Window3 w1 = new Window3();Window3 w2 = new Window3();Window3 w3 = new Window3();w1.start();w2.start();w3.start();}}

死锁的情况:

演示程序死锁的问题(1)不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的资源,就形成了线程的死锁(2)出现死锁后不会出现异常,不会出现提示,只是所有线程都处于阻塞状态,无法继续。所以要避免出现死锁
(3)a线程等待拿到s2的锁,执行完成后释放s1的锁。b线程等待拿到s1的锁,执行完成后释放s2的锁。这样就形成了死锁
package com.jinjian;import javax.swing.plaf.synth.SynthOptionPaneUI;/**
演示程序死锁的问题(1)不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的资源,就形成了线程的死锁(2)出现死锁后不会出现异常,不会出现提示,只是所有线程都处于阻塞状态,无法继续。所以要避免出现死锁(3)a线程等待拿到s2的锁,执行完成后释放s1的锁。b线程等待拿到s1的锁,执行完成后释放s2的锁。这样就形成了死锁*/
public class TestThreadDeadLock {public static void main(String[] args) {StringBuffer s1 = new StringBuffer();StringBuffer s2 = new StringBuffer();new Thread(){@Overridepublic void run(){synchronized (s1){s1.append('a');s2.append('1');try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (s2){s1.append('b');s2.append('2');System.out.println(s1);System.out.println(s2);}}}}.start();new Thread(new Runnable() {@Overridepublic void run() {synchronized (s2){s1.append('C');s2.append('3');try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (s1){s1.append('D');s2.append('4');System.out.println(s1);System.out.println(s2);}}}}).start();}
}
解决线程安全问题方式三:使用Lock-----------JDK5新增面试题:Lock和synchronized之间的异同?相同:二者都可以解决线程安全问题不同:synchronized机制在执行完相应代码后会自动释放同步监视器,Lock需要手动启动同步(lock),和结束同步也需要手动释放锁(unlock)几张同步方式的优先使用顺序Lock-----synchronized同步代码块(已经进入了方法体,分配了相应的资源)------synchronized方法(在方法体之外)
package com.jinjian;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**
解决线程安全问题方式三:使用Lock-----------JDK5新增面试题:Lock和synchronized之间的异同?相同:二者都可以解决线程安全问题不同:synchronized机制在执行完相应代码后会自动释放同步监视器,Lock需要手动启动同步(lock),和结束同步也需要手动释放锁(unlock)几张同步方式的优先使用顺序Lock-----synchronized同步代码块(已经进入了方法体,分配了相应的资源)------synchronized方法(在方法体之外)*/
class Window5 implements Runnable{private int nums = 100;//实例化ReentrantLockprivate ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while (true) {try {//上锁,在锁之间的代码块会被锁住,和synchronized包住的代码块一样,实现线程安全lock.lock();if (nums > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为: " + nums);nums--;} else {break;}}finally {//解锁lock.unlock();}}}
}
public class TestReentrantLock {public static void main(String[] args) {Window5 window5 = new Window5();Thread t1 = new Thread(window5);Thread t2 = new Thread(window5);Thread t3 = new Thread(window5);t1.start();t2.start();t3.start();}
}

JAVA线程安全问题相关推荐

  1. 关于如何解决java线程安全问题?很重要? 快拿小本本记下来!

    关于如何解决java线程安全问题?很重要? 快拿小本本记下来! 线程安全问题 什么是线程安全问题? 线程同步 同步代码块 同步方法 lock显示锁 线程安全问题 什么是线程安全问题? 多个线程操作同一 ...

  2. java线程安全问题之静态变量、实例变量、局部变量

    转载 java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定 ...

  3. java线程安全问题原因及解决办法

    1.为什么会出现线程安全问题 计算机系统资源分配的单位为进程,同一个进程中允许多个线程并发执行,并且多个线程会共享进程范围内的资源:例如内存地址.当多个线程并发访问同一个内存地址并且内存地址保存的值是 ...

  4. java 线程安全问题_java线程安全问题原因及解决办法

    1.为什么会出现线程安全问题 计算机系统资源分配的单位为进程,同一个进程中允许多个线程并发执行,并且多个线程会共享进程范围内的资源:例如内存地址.当多个线程并发访问同一个内存地址并且内存地址保存的值是 ...

  5. volatile关键字和Java线程安全问题

    一.java中的线程安全问题 我们都知道,Java是一种夸平台的语言,因此Java这种语言在处理线程安全问题的时候,会有自己的处理机制,例如volatile关键字,synchronized关键字,并且 ...

  6. java 线程安全问题之静态变量、实例变量、局部变量

    2019独角兽企业重金招聘Python工程师标准>>> java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编 ...

  7. Java 线程安全问题及线程锁(读书笔记)

    多线程安全问题: 首先整理多线程同步的知识点,开头肯定是要先探讨探讨多线程安全的问题.那么嘛叫线程安全问题呢? 答: 我们知道Jvm虚拟机的设计中线程的执行是抢占式的,线程的执行时间是由底层系统决定的 ...

  8. Java 线程安全问题及解决

    线程安全 我们先来说说线程安全问题是什么? 线程安全问题其实就是多个线程同时访问一个资源时,会导致程序运行结果并不是想看到的结果.所以我们建议在没有使用解决方案的时候尽量只读不写 首先我们写了一个简单 ...

  9. java dateformat 线程安全_SimpleDateFormat线程安全问题深入解析

    背景 众所周知,Java中的SimpleDateFormat不是线程安全的,在多线程下会出现意想不到的问题.本文将解析SimpleDateFormat线程不安全的具体原因,从而加深对线程安全的理解. ...

最新文章

  1. A and B and Lecture Rooms CodeForces - 519E LCA+dfs序
  2. 利用Powershell SSH-Session 工具管理 linux或网络设备
  3. 招聘|阿丘科技招系统软件与图像算法工程师(内推)
  4. c语言数组在栈上的分配,彻底弄懂为什么不能把栈上分配的数组(字符串)作为返回值...
  5. springcloud配置文件上传大小_SpringCloud实战二-Nacos
  6. php中绘画控制包括什么,PhpStorm中绘画UML
  7. 科学计算机要用的电池是几号,科学计算器的常识及注意事项
  8. 使用Camel在Amazon上构建分布式工作流应用程序
  9. python分类下取得所有子类_如何找到给定名称的类的所有子类?
  10. [小创造]“XENON”,我的JSON变种。
  11. 推荐七个逆天神器APP,让你分分秒秒变优秀
  12. Class文件 反编译成 Java文件
  13. TX2(linux系统、Ubuntu系统)输入法不显示拼音候选框、下拉框
  14. 【Android 安装包优化】WebP 图片格式 ( WebP 图片格式简介 | 使用 Android Studio 转换 WebP 图片格式 )
  15. 4和2大于号小于号箭头那边_‘’口诀化‘’教学之二――大于号和小于号
  16. 联想服务器系统机房,联想10月1日完成收购IBM x86服务器
  17. Android计步器算法实现(2)
  18. Star CCM+ :迎浪小船 DFBI
  19. VIM复制到系统剪切板
  20. [附源码]java毕业设计网上拍卖系统

热门文章

  1. 京东金融云测平台方案
  2. 基于VoIP视频通话系统构建
  3. 安卓模拟器安装教程_XP系统安装安卓模拟器失败原因解决
  4. ftp服务器文件名格式,ftp服务器文件是什么格式
  5. sprintf 和 snprintf区别
  6. java doc字数_JAVA 仿 MS word 字数统计
  7. 2020年关于Linux的知识技术合集(基础入门到高级进阶)
  8. 联想lenovo ThinkPad笔记本电脑开机进入BIOS的方法
  9. chrome(谷歌浏览器) network看不到请求发送出的url信息
  10. 数字化升级的技术原力:数据编织+决策智能