java中解决脏读_多线程出现脏读以及解决方法(使用synchronized)
使用多线程出现脏读,得到的结果不是设计时想要的怎么办呢?
直接看示例:
出现脏读的程序
DealThread.java
public class DealThread implements Runnable {
private String username;
public void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
System.out.println(" in run " + Thread.currentThread().getName() + " " + username);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" out run " + Thread.currentThread().getName() + " " + username);
}
}
Run2_2.java
public class Run2_2 {
public static void main(String[] args) {
DealThread d1 = new DealThread();
d1.setUsername("aa");
Thread t1 = new Thread(d1,"A");
t1.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
d1.setUsername("bb");
Thread t2 = new Thread(d1,"B");
t2.start();
}
}
输出结果是:
in run A aa
in run B bb
out run A bb
out run B bb
加同步锁和使用不同的DealThread对象都能解决这个问题,但是同步锁加得不对还是不能解决问题的,比如修改DealThread.java
修改方法1:(不能解决)
public class DealThread implements Runnable {
private String username;
public void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
synchronized (this) {
System.out.println(" in run " + Thread.currentThread().getName() + " " + username);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" out run " + Thread.currentThread().getName() + " " + username);
}
}
}
输出结果为:
in run A aa
out run A bb
in run B bb
out run B bb
还是没达到效果,这样已经做对一半了,再给 setUsername加上synchronized就可以了
修改方法2:
public class DealThread implements Runnable {
private String username;
public synchronized void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
synchronized (this) {
System.out.println(" in run " + Thread.currentThread().getName() + " " + username);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" out run " + Thread.currentThread().getName() + " " + username);
}
}
}
这样输出结果就为:
in run A aa
out run A aa
in run B bb
out run B bb
另外一种改法就是修改Run2_2.java 为每个线程分配一个DealThread对象,这样就不会出现脏读
修改方法3:
public class Run2_2 {
public static void main(String[] args) {
DealThread d1 = new DealThread();
d1.setUsername("aa");
Thread t1 = new Thread(d1,"A");
t1.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
DealThread d2 = new DealThread();
d2.setUsername("bb");
Thread t2 = new Thread(d2,"B");
t2.start();
}
}
这样的话两个线程会异步打印出各自的内容,互不影响,效率也会快一点,因为不用等上一个线程释放锁。
结合前面两篇关于多线程synchronized还可以这样改(个人觉得这样比较符合实际开发)
修改方法4:
新建merch.java
public class merch {
private String username;
public String getUsername() {
return username;
}
public synchronized void setUsername(String username) {
this.username = username;
}
}
修改DealThread.java
public class DealThread implements Runnable {
private merch merchA;
DealThread (merch merchA) {
this.merchA = merchA;
}
@Override
public void run() {
synchronized (merchA) {
System.out.println(" in run " + Thread.currentThread().getName() + " " + merchA.getUsername());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" out run " + Thread.currentThread().getName() + " " + merchA.getUsername());
}
}
}
修改Run2_2.java
public class Run2_2 {
public static void main(String[] args) {
merch merchA = new merch();
merchA.setUsername("aa");
DealThread d1 = new DealThread(merchA);
Thread t1 = new Thread(d1,"A");
t1.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
merchA.setUsername("bb");
Thread t2 = new Thread(d1,"B");
t2.start();
}
}
这样运行结果还是:
in run A aa
out run A aa
in run B bb
out run B bb
原理还是给 setUsername 和 输出的代码块加锁
个人即兴写的程序和临时想到的解决方法,如果更优的解决方法请留下高见,谢谢。
java中解决脏读_多线程出现脏读以及解决方法(使用synchronized)相关推荐
- java中virtual关键字_浅谈virtual、abstract方法和静态方法、静态变量理解
说点对这几个容易混淆的词的理解: 1.c++中的virtual方法的 virtual关键字主要是防止继承中重复继承父类的同一个方法而设置的标识. 2.virtual与abstract关键字的不同之处在 ...
- java socket建立长连接_Java Web项目中使用Socket通信多线程、长连接的方法
很多时候在javaweb项目中我们需要用到Socket通信来实现功能,在web中使用Socket我们需要建立一个监听程序,在程序启动时,启动socket监听.我们的应用场景是在java项目中,需要外接 ...
- Java中为什么有时候通过指定编码集无法解决乱码
@TOC Java中为什么有时候通过指定编码集无法解决乱码 当我们编程的时候都遇到过出现乱码的情况,这通常是使用了不匹配的编码表导致的,这是我们可以用指定的编码表的方式解决乱码问题如下面 的代码 St ...
- Java中常见的CMS GC问题分析与解决(一)
Java中常见的CMS GC问题分析与解决(一) 目前,互联网上 Java 的 GC 资料要么是主要讲解理论,要么就是针对单一场景的 GC 问题进行了剖析,对整个体系总结的资料少之又少.前车之鉴,后事 ...
- java 中的枚举_说说Java中的枚举(一)
在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的.例如星期一到星期日七个数据元素组成了一周的"数据 ...
- java sleep唤醒_详解Java中的线程让步yield()与线程休眠sleep()方法
Java中的线程让步会让线程让出优先级,而休眠则会让线程进入阻塞状态等待被唤醒,这里我们对比线程等待的wait()方法,来详解Java中的线程让步yield()与线程休眠sleep()方法 线程让步: ...
- java类名可以是数字吗_在 Java 中,一个类可同时定义许多同名的方法,这些方法的形式参数的个数、类型或顺序各不相同,传回的值也可以不相同。这种面向对象程序特性称为( )。_学小易找答案...
[简答题]Java 支持多继承吗 ? [单选题]以下关于继承的叙述正确的是( ). [单选题]在 Java 中,一个类可同时定义许多同名的方法,这些方法的形式参数的个数.类型或顺序各不相同,传回的值也 ...
- 计算机桌面怎么设置在开始菜单,电脑桌面开始菜单不见了应该如何解决?_开始菜单不见了解决办法介绍...
电脑桌面开始菜单不见了应该如何解决?_开始菜单不见了解决办法介绍 2018-06-22 16:26:29 近期朋友在电脑使用过程中,电脑桌面的开始菜单突然就消失不见了,以为重启之后就会成功显示出来,但 ...
- java中char类型转换成int类型的两种方法
java中char类型转换成int类型的两种方法 方法一: 第一种利用Integer包装类的方法Integer.parseInt Copychar ch = '9'; if (Character.is ...
最新文章
- 谷歌程序员少输一个“”,差点让全球Chrome笔记本变砖
- 理解 Memory barrier(内存屏障)无锁环形队列
- C语言实现最简单的2048小游戏
- mongodb update
- 一个对象的内存图及运行流程和3个对象的内存图的运行流程
- STM32 之十一 LL 库(low-layer drivers)详解 及 移植说明
- servlet 配置 使用_配置HTTPS以与Servlet一起使用
- python两个中文队列比较_具有两个优先级的优先级队列Python
- leetcode python3 简单题14. Longest Common Prefix
- 学习iptables
- 怀念经理用鼠标线联网的1990年代当时
- Java实现部标JTT1078实时音视频传输指令——视频流负载包(RTP)传输
- NoSQL--Redis
- m4a怎么转换成mp3,m4a转mp3方法
- java dao 是什么_dao java是什么
- C#上位机开发串口通信编程——倒计时器开发
- 计算机应用安全检查通报,Microsoft 安全通报 4092731
- 关于vlc播放器的ActiveX控件调用问题
- java 创建目录及文件_java中如何在系统目录下创建文件夹和文件
- 里约奥运会闭幕,中国获奖牌榜前三甲
热门文章
- C++虚继承(四) --- /d1 reportSingleClassLayout插入看类内存布局
- 豆瓣9.8分,周志明的《凤凰架构》,高屋建瓴,推荐(送书)
- 忘掉Java并发,先听完这个故事...
- 【今晚9点】:对话袁荣喜——一名C程序员的打怪之路
- 知乎云敲钟、比特币可购买特斯拉、用户隐私收集新规五一生效、 软件疯长等|Decode the Week...
- Linux AV1硬件视频解码将支持Intel Tiger Lake
- x265发起者陈敏:别人看我是专注,其实我只是感兴趣而已
- 深度学习为图片压缩算法赋能:节省55%带宽
- ffplay.c学习-2-数据读取线程
- 十个问题理解Linux epoll工作原理