Java第二十四天,线程安全
线程安全
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第二十四天,线程安全的更多相关文章
- “全栈2019”Java第二十四章:流程控制语句中决策语句switch下篇
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 学JAVA第二十四天,Set集合与StringBuilder
下面的内容需要慢慢看,因为,我的语言表达能力不是很好 首先说Set把,Set集合是一个无序且不允许重复的集合,而且查找效率也是快的可怕的. 但是,有些时候,我们必须要用储存多个相同的值时,Set也是可 ...
- “全栈2019”Java多线程第二十四章:等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- javaSE第二十四天
第二十四天 363 1:多线程(理解) 363 (1)JDK5以后的Lock锁 363 A:定义 363 B:方法: 364 C:具体应用(以售票程序为例) 364 ...
- Gradle 1.12用户指南翻译——第二十四章. Groovy 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- Java 1.ExecutorService四种线程池的例子与说明
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- NeHe OpenGL教程 第二十四课:扩展
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- Python第二十四天 binascii模块
Python第二十四天 binascii模块 binascii用来进行进制和字符串之间的转换 import binascii s = 'abcde' h = binascii.b2a_hex(s) # ...
- SQL注入之Sqli-labs系列第二十四关(二阶注入)
开始挑战第二十四关(Second Degree Injections) 0x1 前言 SQL注入一般分为两类:一阶SQL注入(普通SQL注入),二阶SQL注入 .二次注入不是注入两次的意思,请不要混淆 ...
随机推荐
- 测试必知必会系列- Linux常用命令 - tar
21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 压缩一 ...
- (转)协议森林03 IP接力赛 (IP, ARP, RIP和BGP协议)
协议森林03 IP接力赛 (IP, ARP, RIP和BGP协议) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 网络层(net ...
- C结构体与链表
今天来总结C语言的学习盲点--结构体,为了不显单一,也为了补足作者链表的编程缺陷,特更此博文,总结近段时间的学习成果.话不多说,先上一段代码 struct none{int item; link ne ...
- 聊聊OkHttp实现WebSocket细节,包括鉴权和长连接保活及其原理!
一.序 OkHttp 应该算是 Android 中使用最广泛的网络库了,我们通常会利用它来实现 HTTP 请求,但是实际上它还可以支持 WebSocket,并且使用起来还非常的便捷. 那本文就来聊聊, ...
- Vulnhub靶场DC-1 WP
前言 之前提到过最近在做vlunhub的靶场复现工作,今天开始更新writeup吧.(对着walkthrough一顿乱抄嘻嘻嘻) 关于DC-1(官网翻译来的) 描述 DC-1是一个专门构建的易受攻击的 ...
- Fiddler4 手机抓包
1.要对计算机Fiddler进行配置,允许远程计算机连接. 2.保证手机电脑在同一局域网中. 3.手机上设置代理服务器.以华为手机为例,设置-->WLAN-->找到并长按目前所连接的WiF ...
- 配置GitLab或Git环境之教程
配置GitLab或Git环境之教程 1.安装好Git后,首先打开开始菜单的所有程序里面的git文件夹,打开Git Bash/ 2.弹出的命令行里面输入ssh-keygen 输入y,一直Enter ...
- 3. webdriver的常用方法
WebDriver常用方法: clear(): 清除文本. send_keys (value): 模拟按键输入. click(): 单击元素. submit():用于提交表单 from seleniu ...
- 理解Raft协议
目录 1.Paxos算法存在的问题 2.Raft算法 2.1 复制状态机 2.2. Raft算法 2.2.1 安全性问题 2.2.2 Leader选举 2.2. ...
- R之Shiny学习笔记
官方教程:https://shiny.rstudio.com/tutorial/ 中文教程:http://yanping.me/shiny-tutorial/ 英文教程:https://deanatt ...