java数据同步陷阱
并发,我的理解就是同时运行多个程序。同时,难以避免的就是数据的同步问题,如果数据同步问题处理不好就很容易造成程序出现bug,当然,对于其造成的危害,不加详述。
首先,来看一个简单的例子,当然,这个例子也并非是我发现的。
public class StopTread {
private static boolean stopRequested;
static Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while(!stopRequested)
{
i++;
}
}
});
public static void main(String[] args) throws InterruptedException
{
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
造成这个问题的原因在于当主线程修改了stopRequested变量后,后台线程并没有及时的读取到最新的值,因此,造成了后台线程会一直运行下去。代码内容很容易理解,就是通过一个变量来控制线程的停止与运行而已。当stopRequested被主线程设置为true时,后台线程就终止运行。但是,这个程序中并没有对stopRequested做数据同步处理,这就造成了数据的不安全性,当然,并不是在所有情况都能发生这个数据的不安全性的。但至少理论上是存在,同时,我也花费了很长的时间,模拟出了这个不安全性的存在。
根据相关资料解释其原因为:
while(!stopRequested)
{
i++;
}
被优化成了:
if(!stopRequested)
while(true)
i++;
也正是由于这个优化导致了程序无法前进执行。
对于解决这个问题的方法有两种:其一是通过锁机制,其二是通过volatile修饰符。
方法一:
public class StopTread {
private static boolean stopRequested;
static Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while(!stopRequested())
{
i++;
}
}
});
private static synchronized void requestStop()
{
stopRequested = true;
}
private static synchronized boolean stopRequested()
{
return stopRequested;
}
public static void main(String[] args) throws InterruptedException
{
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
可以发现,写方法和读方法都被同步了,只同步写方法是不能实现,如果没有对读和写方法都进行同步的话,同步是不会起作用的。
方法二:
public class StopTread {
private static volatile boolean stopRequested;
static Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while(!stopRequested)
{
i++;
}
}
});
public static void main(String[] args) throws InterruptedException
{
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
Volatile的修饰符不执行互斥访问,但是可以保证一个县城在读取该域的时候就讲看到最近刚刚被写入的值。
java数据同步陷阱的更多相关文章
- java 线程数据同步
java 线程数据同步 由买票实例 //java线程实例 //线程数据同步 //卖票问题 //避免重复卖票 //线程 class xc1 implements Runnable{ //定义为静态,可以 ...
- Java多线程初学者指南(9):为什么要进行数据同步
Java中的变量分为两类:局部变量和类变量.局部变量是指在方法内定义的变量,如在run方法中定义的变量.对于这些变量来说,并不存在线程之间共享的问题.因此,它们不需要进行数据同步.类变量是在类中定义的 ...
- Java多线程学习笔记——从Java JVM对多线程数据同步的一些理解
我们知道在多线程编程中,我们很大的一部分内容是为了解决线程间的资源同步问题和线程间共同协作解决问题.线程间的同步,通俗我们理解为僧多粥少,在粥有限情况下,我们怎么去防止大家有秩序的喝到粥,不至于 ...
- JAVA通过Gearman实现MySQL到Redis的数据同步(异步复制)
MySQL到Redis数据复制方案 无论MySQL还是Redis,自身都带有数据同步的机制,像比较常用的 MySQL的Master/Slave模式 ,就是由Slave端分析Master的binlog来 ...
- java实现高性能的数据同步
最近在做一个银行的生产数据脱敏系统,今天写代码时遇到了一个“瓶颈”,脱敏系统需要将生产环境上Infoxmix里的数据原封不动的Copy到另一台 Oracle数据库服务器上,然后对Copy后的数据作些漂 ...
- Java多线程学习---------超详细总结(java 多线程 同步 数据传递 )
目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么 ...
- java线程基础巩固---数据同步引入并结合jconsole,jstack以及汇编指令认识synchronized关键字
对于多线程编程而言其实老生成谈的就是数据同步问题,接下来就会开始接触这块的东东,比较麻烦,但是也是非常重要,所以按部就班的一点点去专研它,下面开始. 数据同步引入: 这里用之前写过的银行叫号的功能做为 ...
- java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁
多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...
- 大数据实践-数据同步篇tungsten-relicator(mysql->mongo)
// mongo)";digg_bgcolor = "#FFFFFF";digg_skin = "normal"; // ]]> // [导读] ...
随机推荐
- redis命令之lrange
LRANGE key start stop Related commands BLPOP BRPOP BRPOPLPUSH LINDEX LINSERT LLEN LPOP LPUSH LPUSHX ...
- ambari安装过程中的问题汇总
今天重新安装ambari过程中,遇到了几个问题,耗费了我很长时间,在此记录一下 ambari重新安装可参考我之前的一篇随笔 http://www.cnblogs.com/6tian/p/4097401 ...
- Java同步块(synchronized block)使用详解
Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(synchronzied) 实例方法同步 静 ...
- C++/C#/java开发支持求解
本人大一学C语言,大二学VB,大三学VC,毕业后工作前两年用C++,接着两年用C#,最近几个月Android开发用Java. 以下本人总结以下,有些疑惑希望大师帮忙解答. 1. C语言,精简,灵活,适 ...
- C# LINQ详解(一)
原文标题:How does it work in C#?-Part 3 (C# LINQ in detail),作者:Mohammand A Rahman. 目录 LINQ 基础 扩展方法-幕后的工作 ...
- PagerSlidingTabStrip
https://github.com/jpardogo/PagerSlidingTabStrip
- 为一张PCI卡打通经络的过程
一张PCI卡通过“一转二”的转接卡插在主板上,probe调用失败,日志显示读取配置空间的时候发生了奇偶校验错误,可是使用相同的转接卡把它插在另外一台相同机器的主板上时,却运行正常,这就说明不是转接卡的 ...
- sigar监控
相关参照博客: http://liningjustsoso.iteye.com/blog/1254584 http://blog.csdn.net/aoxida/article/category/12 ...
- MHA工作原理
http://my.oschina.net/u/1440383/blog/313798?fromerr=Tvth3ODF
- java与.net比较学习系列开发环境和常用调试技巧常用操作快捷键
调试 F5 F11 调试运行 CTRL+F5 暂无 非调试运行 F6 不适用 编译整个解决方案 SHIFT+F6 不适用 编译当前选择的工程 SHIFT+F5 CTRL ...