线程安全

1.定义

多线程访问共享数据,会产生线程安全问题。

2.代码模拟

卖票Ticked类:

package com.lanyue.day22;

public class Person {

    public static void main(String[] args) {

        Car one = new Car("宝马");

        one.start();

        Driver two = new Driver();
new Thread(two).start(); new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0;i < 5;i++){ try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第二个司机第" + i + "次报数中。");
}
}
}).start();
}
}

卖票窗口Window类

package com.lanyue.day23;

public class Windows {

    public static void main(String[] args) {

        Ticked runnable = new Ticked();
Thread one = new Thread(runnable);
Thread two = new Thread(runnable);
Thread three = new Thread(runnable); one.start();
two.start();
three.start();
}
}

程序执行图

3.解决方法

当使用多个线程对同一个资源有写操作时,就容易出现线程安全问题。为解决这个问题,Java提供了同步机制synchronized来解决这个问题。

那么如何实现所谓的同步机制呢?有三个方法:

1.同步代码块

synchronized用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

示例:

synchronized (同步锁){
//代码块.

注意:

(1)同步代码块中的锁对象可以是任意对象。

(2)必须保证多个线程使用的锁对象是同一个对象。

示例代码:

package com.lanyue.day23;

public class Ticked implements Runnable {

    public Integer ticks = 100;
public Object obj = new Object();
public boolean state = true; @Override
public void run() { while(state){ synchronized (obj){ if(ticks-- > 0){ System.out.println(Thread.currentThread().getName() + "窗口卖出了第" + (100 - ticks) + "张票"); }else{ state = false;
}
}
}
}
}

2.同步方法

(1)普通同步锁方法:

只需要在方法前加一个修饰符 synchronized 即可(本质上也是利用锁对象锁定的,这个锁是this)。

格式:

权限修饰符 synchronized 返回值类型 方法名(参数){

方//法体

示例代码:

package com.lanyue.day23;

public class TickedTwo implements Runnable{

    public Integer ticks = 100;
public boolean state = true; @Override
public void run(){ while(state){ view();
}
} public synchronized void view(){ if(ticks-- > 0){ System.out.println(Thread.currentThread().getName() + "窗口卖出了第" + (100 - ticks) + "张票"); }else{ state = false;
}
}
}

(3)静态同步方法

本质也是利用锁对象,这个锁对象是class文件对象

格式:

权限修饰符 static synchronized 返回值类型 方法名(参数){

//方法体。

示例代码:

package com.lanyue.day23;

public class TickedThree implements Runnable{

    public static Integer ticks = 100;
public static boolean state = true; @Override
public void run() { while(state){ view();
}
} public static synchronized void view(){ if(ticks-- > 0){ System.out.println(Thread.currentThread().getName() + "窗口卖出了第" + (100 - ticks) + "张票"); }else{ state = false;
}
}
}

3.锁机制

Lock接口

ReentrantLock类是Lock接口的实现类。

使用步骤:

(1)在成员变量位置创建 ReentrantLock 对象。

(2)在可能发生线程安全问题的代码前调用ReentrantLock 对象的lock()方法锁住共享数据。

(3)在可能发生线程安全问题的代码后调用ReentrantLock  对象的unlock()方法解锁共享资源。

代码示例:

package com.lanyue.day23;

import java.util.concurrent.locks.ReentrantLock;

public class TickedFour implements Runnable {

    public ReentrantLock myLock = new ReentrantLock();
public Integer ticks = 100;
public boolean state = true; @Override
public void run() { while(state){ myLock.lock();
if(ticks-- > 0){ System.out.println(Thread.currentThread().getName() + "窗口卖出了第" + (100 - ticks) + "张票"); }else{ state = false;
} myLock.unlock();
}
}
}

Java第二十四天,线程安全的更多相关文章

  1. “全栈2019”Java第二十四章:流程控制语句中决策语句switch下篇

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  2. 学JAVA第二十四天,Set集合与StringBuilder

    下面的内容需要慢慢看,因为,我的语言表达能力不是很好 首先说Set把,Set集合是一个无序且不允许重复的集合,而且查找效率也是快的可怕的. 但是,有些时候,我们必须要用储存多个相同的值时,Set也是可 ...

  3. “全栈2019”Java多线程第二十四章:等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  4. javaSE第二十四天

    第二十四天    363 1:多线程(理解)    363 (1)JDK5以后的Lock锁    363 A:定义    363 B:方法:    364 C:具体应用(以售票程序为例)    364 ...

  5. Gradle 1.12用户指南翻译——第二十四章. Groovy 插件

    其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...

  6. Java 1.ExecutorService四种线程池的例子与说明

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...

  7. NeHe OpenGL教程 第二十四课:扩展

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. Python第二十四天 binascii模块

    Python第二十四天 binascii模块 binascii用来进行进制和字符串之间的转换 import binascii s = 'abcde' h = binascii.b2a_hex(s) # ...

  9. SQL注入之Sqli-labs系列第二十四关(二阶注入)

    开始挑战第二十四关(Second Degree Injections) 0x1 前言 SQL注入一般分为两类:一阶SQL注入(普通SQL注入),二阶SQL注入 .二次注入不是注入两次的意思,请不要混淆 ...

随机推荐

  1. Windows Server 2012 R2 域证书服务搭建

    网管大叔说要给每个人颁发一个证书,这个证书很耗电 1.在服务器管理器中添加角色和功能 下一步 下一步 勾选Active Directory证书服务 下一步 下一步 勾选证书颁发机构,证书颁发机构Web ...

  2. Git 基础入门

    目录 git安装 基本设置 创建版本库 相关概念 将代码提交到分支仓库 版本回退 代码修改 撤销修改 文件删除 github 远程仓库 添加远程仓库 克隆远程仓库 分支操作 忽略特殊文件 git安装 ...

  3. SpringBoot 集成MQTT配置

    目录 1. 前言 2. MQTT介绍 3. SpringBoot 集成MQTT 3.1 导入mqtt库 3.2 配置MQTT订阅者 3.3 配置MQTT发布者 3.4 MQTT消息处理和发送 3.4. ...

  4. Web过滤器和监听器

    1.过滤器 1.1什么是过滤器 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servle ...

  5. python 顺序读取文件夹下面的文件(自定义排序方式)

    我们在读取文件夹下面的文件时,有时是希望能够按照相应的顺序来读取,但是 file_lists=os.listdir()返回的文件名不一定是顺序的,也就是说结果是不固定的.就比如读取下面这些文件,希望能 ...

  6. python-模块的发布和安装

    当我们 import python 模块时,默认先在当前路径搜索,如果当前路径找不到目标模块,python会到安装目录找,还找不到则抛出异常. 如果我们想让自己写的模块,能跟系统自带模块一样,在任何地 ...

  7. EFCore DbContext 报SqlException: Incorrect syntax near 'OFFSET'.

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSq ...

  8. 凸包问题 Graham Scan

    2020-01-09 15:14:21 凸包问题是计算几何的核心问题,并且凸包问题的研究已经持续了好多年,这中间涌现出了一大批优秀的算法. 凸包问题的最优解法是Graham Scan算法,该算法可以保 ...

  9. JS十大经典排序排序算法

    1.冒泡排序 冒泡排序通常排在第一位,说明它是排序算法的入门算法,是最简单的一个排序算法,而且必须掌握和理解. 先来看看代码吧: function bubbleSort(arr) { let temp ...

  10. css 重排与重绘

    css 重绘与重排 我们要知道当浏览器下载完页面的所有资源后,就会开始解析源代码. HTML 会被解析成 DOM Tree,Css 则会被渲染成 CSSOM Tree,最后它们会附加到一起,形成渲染树 ...