Java,多个线程对同一个数据源的访问
当多个线程对同一个数据源进行访问时,应对线程同步或加锁。
为何?举个简单的例子:有一个共享的数据源dataSource,其值为0。有两个线程,Thread1和Thread2。
Thread1的任务是将dataSource连续自增10次,
Thread2的任务是将dataSource连续自减10次,
当两个线程的任务都完成时,最终的dataSource的值应为0,事实上,可能不为0,请看示例1:
import static java.lang.System.out;
public class LockTest1
{
private static int dataSource;
private static class Task1 implements Runnable
{
public void run()
{
for (int i = 0; i < 10; ++i)
{
out.printf("Task1 --- dataSource: %d\n", dataSource);
int t = dataSource + 1;
try
{
Thread.sleep(1);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
finally
{
dataSource = t;
}
}
}
}
private static class Task2 implements Runnable
{
public void run()
{
for (int i = 0; i < 10; ++i)
{
out.printf("Task2 --- dataSource: %d\n", dataSource);
int t = dataSource - 1;
try
{
Thread.sleep(10);
dataSource = t;
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
finally
{
dataSource = t;
}
}
}
}
public static void main(String[] args) throws InterruptedException
{
Thread thread1 = new Thread(new Task1());
Thread thread2 = new Thread(new Task2());
thread1.start();
thread2.start();
Thread.sleep(1000);
out.printf("The value of dataSource is %d.", dataSource);
}
}
import static java.lang.System.out;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockTest2
{
private static int dataSource;
private static ReentrantReadWriteLock.WriteLock lock = new ReentrantReadWriteLock().writeLock();
private static class Task1 implements Runnable
{
public void run()
{
lock.lock();
for (int i = 0; i < 10; ++i)
{
int t = dataSource + 1;
out.printf("Task1 --- 自增前 --- dataSource: %d\n", dataSource);
try
{
Thread.sleep(1);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
finally
{
dataSource = t;
out.printf("Task1 --- 自增后 --- dataSource: %d\n", dataSource);
}
}
lock.unlock();
}
}
private static class Task2 implements Runnable
{
public void run()
{
lock.lock();
for (int i = 0; i < 10; ++i)
{
out.printf("Task2 --- 自增前 --- dataSource: %d\n", dataSource);
int t = dataSource - 1;
try
{
Thread.sleep(10);
dataSource = t;
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
finally
{
dataSource = t;
out.printf("Task2 --- 自增后 --- dataSource: %d\n", dataSource);
}
}
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException
{
Thread thread1 = new Thread(new Task1());
Thread thread2 = new Thread(new Task2());
thread1.start();
thread2.start();
Thread.sleep(300);
//睡眠一段时间,确保thread1和thread2执行完毕后再打印dataSource的值
out.printf("dataSource的值为%d.", dataSource);
}
}
Java,多个线程对同一个数据源的访问的更多相关文章
- 第36节:Java当中的线程
Java当中的线程 Java当中的线程,进程和线程的关系?进程就是线程吗?不是的.线程的运行,和方法. 多线程和多进程,多进程为在操作系统中同时进行多个应用程序,如你的电脑可以同时听音乐,同时上网,手 ...
- java多线程之线程安全
线程安全和非线程安全是多线程的经典问题,非线程安全会在多个线程对同一个对象并发访问时发生. 注意1: 非线程安全的问题存在于实例变量中,如果是方法内部的私有变量,则不存在非线程安全问题. 实例变量是对 ...
- Java多线程 3 线程同步
在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的 ...
- JAVA中的线程安全与非线程安全
原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...
- Java面试题-线程安全
1. 什么叫线程安全?servlet是线程安全吗? 答:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他 ...
- Java并发3-多线程面试题
1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速. 2) 线程和进程有什 ...
- Java中的线程Thread总结
首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的! 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口. 要注意的是Threa ...
- Java值创建线程的两种方式对比
在Java中创建线程的方式有两种,第一种是直接继承Thead类,另一种是实现Runable接口.那么这两种方式孰优孰劣呢? 采用继承Thead类实现多线程: 优势:编写简单,如果需要访问当前线程,只需 ...
- Java多线程之线程其他类
Java多线程之线程其他类 实际编码中除了前面讲到的常用的类之外,还有几个其他类也有可能用得到,这里来统一整理一下: 1,Callable接口和Future接口 JDK1.5以后提供了上面这2个接口, ...
随机推荐
- 对拍程序(Win)
代码如下: @echo off :again rand.exe echo "rand finish" asd.exe echo "1.exe finish" 未 ...
- TeraTerm设定(窗体大小,字体字号)保存为默认值
Tera Term是一款很好的SSH工具,大家经常遇到一个头疼的问题,每次打开的时候,都要自己重新设置一遍Font. 介绍一下把自己喜欢的字体,设置好后,保存到默认配置中的方法. 设置窗体大小: 设置 ...
- angularjs bootstrap 简介
1.angular特色 数据双向绑定 模块化 var myapp=angular.module... 控制器 myapp.controller(){} 2.bootstrap特色 栅格结构 cs ...
- STL中heap用法
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; ]={,, ...
- 洛谷 [P3224] 永无乡
Treap 的合并 首先感谢 @Capella 的DeBug 其次,这是由一个 & 号引发的血案 注意对于所有修改操作都要 & Treap的合并, 启发式合并,对于每一个节点都 ins ...
- Codeforces 271D - Good Substrings [字典树]
传送门 D. Good Substrings time limit per test 2 seconds memory limit per test 512 megabytes input stand ...
- Codeforces Round #268 (Div. 2) D. Two Sets [stl - set + 暴力]
8161957 2014-10-10 06:12:37 njczy2010 D - Two Sets GNU C++ A ...
- iOS7 毛玻璃效果
转自:http://prolove10.blog.163.com/blog/static/138411843201391401054305/ 原图: 效果图: 实现:首先需要导入Accelerat ...
- android获取手机号
private String getPhoneNum(){ //与手机建立连接 TelephonyManager tm = (TelephonyManager)getSystemService(Con ...
- SPOJ 1479 +SPOJ 666 无向树最小点覆盖 ,第二题要方案数,树形dp
题意:求一颗无向树的最小点覆盖. 本来一看是最小点覆盖,直接一下敲了二分图求最小割,TLE. 树形DP,叫的这么玄乎,本来是线性DP是线上往前\后推,而树形DP就是在树上,由叶子结点状态向根状态推. ...